第五章 子类与继承

5.1 子类与父类

子类(派生类)

1、由其他类派生出的类

2、子类继承父类的所有非私有成员(不包含构造器)

3、子类只能继承自一个父类(单继承)

父类(超类、基类)

1、派生出子类的类叫做父类

2、包含了一些共同特征(属性与行为)

继承语法--extends关键字

class 子类名 extends 父类{

      //类体代码
}

5.1.1 子类

以下是在父类A下定义子类B

class A {
    …
}
class B extends A { //定义A的子类B
    …
}

5.1.2 类的树形结构

  • Java的类按继承关系可形成树形结构
  • 根节点为Object类(Java自带类)
  • 没有使用extends关键字的类,父类默认为Object类(“祖先类”)

5.2 子类的继承性 

为什么要有继承,有很多子类可能会用到一样的方法,一个一个的子类中打太麻烦,直接在它们父类中定义好就搞定。你后期想写“物种多样性”也可以再在子类中重写方法也可以。(重写方法会在后面讲)

5.2.1 子类和父类在同一包中的继承性

  • 用关键字extends定义的一个子类,其父类中的没带private的方法或变量都可被我这个子类定义的实例对象使用。
  • private英文即私有的,“爸爸不想给儿子的东西”,子类定义的实例变量就不可以用private了的方法或变量。
  • 其实继承就是,子类继承了父类的方法或变量,相当于子类自己定义了一样。如下面两例代码效果相当:

例1

class A {
    void f1(){
        …
    }
    private void f2() {
        …
    }
}
class B extends A {
}

例2

class B {
    void f1(){
        …
    }
}

5.2.2 子类和父类不在同一包中的继承性

子类父类不在同一包中,子类只能继承到父类的protected和public的方法或变量。

5.3 子类与对象

当用子类的构造方法创建一个对象时,不仅子类中声明的成员变量被分配了内存空间,而且父类的成员变量也都被分配了内存空间,但只将其中一部分(即子类继承的那部分成员变量)作为分配给子类对象的变量

5.3.1子类对象的特点

也不是父类中有private的变量,子类的实例对象就获取不到它的值了。就算是未被子类继承的变量,也可以通过被子类继承的方法然后获取到其值(其指的是未被子类继承的变量)。

例:

class A {
    private int a = 555; //私有变量,子类不可继承
    int f() {
        return a; //这个方法不是私有的,但返回了其类的私有变量的值,像个间谍一样,“出卖我的爱,没了良心在~”
    }
}
class B extends A {
}
public class MainC {
    public static void main(String args[]) {
        B abc = new B();
        System.out.println(abc.f()); //输出的是555,那个“被出卖的a”
        //System.out.println(abc.a);  //非法
    }
}

运行结果:

简单来说就是环环相扣,子类B的对象可以调用继承的方法f(),f()又可以返回父类A中的private了的a的值。

5.3.2 Instanceof运算符

语法:对象 instanceof 类

作用:instanceof运算符是Java独有的运算符,其左边的操作元是对象,右边的操作员是类。当左边的对象属于右边的类或其子类创建的对象,该运算结果为true,否则结果为false。

例:

//Apple是Fruit的子类
Fruit fruit = new Fruit();
Apple apple = new Apple();
System.out.println(fruit instanceof Apple); // 输出 false
System.out.println(apple instanceof Apple); // 输出 true
System.out.println(apple instanceof Fruit); // 输出 true

5.4 成员变量的隐藏和方法重写

作用:把父类的“改”成自己的。

成员变量的隐藏和方法重写,这个名词看上去好像挺复杂,其实基本上是一个东西。

5.4.1 成员变量的隐藏

子类继承的父类的变量,子类又把这个变量写了遍,之后调用  子类的实例对象.变量 返回的就是子类中的变量值了。

以下是一个河豚案例,

例:

class Fish {
    int heTun = 20;
}
class AdultFish extends Fish {
    float heTun = 20f;
}
public class MainC {
    public static void main(String[] args){
        AdultFish fishCount = new AdultFish();
        System.out.println(fishCount.heTun); //输出为20.0并非20
    }
}

运行结果:

就像爸爸我留给你了一辆保时捷跑车(父类中的变量),之后儿子你很爱惜它,把它留在了温室中,整天开着Jeep(子类中的同名变量)出去兜风。

5.4.2 方法重写(方法覆盖)

方法重写,如字面意思,同上面的变量的隐藏差不多,只不过多了一些重写方法时的要求(不按要求,会非法):

1.子类不可重写父类中的final方法 ,final方法如下:

class A {
    final void f() {
        …
    }
}
class B extends A {
    void f() { //非法
        …
    }
}

2.不可降,可提高:即访问权限不可降,只可提高。(访问限制修饰符权限降序:public>protected>友好的>private)

class A {
    protected int f(int a) {
        …
    }
}
class B extends A {
    int f(int a) { //默认友好,protected>友好,不可降低访问权限,非法
        …
    }
}
class C extends A {
    public int f(int a) { //public>protected,提高了访问权限,合法
        …
    }
}

3.参数数据类型一致:由于涉及到关系重载,在子类中重写某个父类中的某方法时,参数数量方法返回值的数据类型等都得和前者一样。

class A {
    int f(int a) {
        …
    }
}
class B extends A {
    int f(int a, int b) { //参数数量不一,非法
        …
    }
}
class C extends A {
    float f(int a) { //返回的数据类型变了,非法
        …
    }
}

5.5 super关键字

5.5.1 用super操作被隐藏的成员变量和方法

super可以获取到父类的成员变量的值。

例:

class A {
    int n = 6;
    int f() {
        return n; // 6
    }
}
class B extends A {
    int n;

    int f() {
        n = super.n; //🍍,其中调用了super.n,也就是A类中的n的值6,所以abc.f()返回值为6而不是8。
        return n; // 6
    }
}
public class MainC {
    public static void main(String[] args) {
        B abc = new B(); //从这开始读——————
        abc.n = 8; //让B类下的n的值为8
        System.out.println(abc.f()); //进入重写的f()函数,(现在跳转到上面的🍍处继续阅读)
    }
}

运行结果:

5.5.2 使用super调用父类的构造方法

在子类的构造方法中使用super可以调用父类的构造方法

//每个子类的构造方法的头一个语句默认有
super();

在父类中定义多个构造方法时应当包括一个不带参数的构造方法,以防在子类的构造方法省略写super方法时出错。

例:

class A {
    int a;
    A() { //A的构造方法
    }
    A(int a) { //A的构造方法的重载
        this.a = a;
        System.out.println("a:" + this.a);
    }
}
class B extends A {
    int b = 6;
    B(int b) {
        super(6); //调用的是父类A中的A(int a)方法
        this.b = b;
        System.out.println("b:" + this.b);
    }
}
public class MainC {
    public static void main(String[] args) {
        B abc = new B(8);
    }
}

运行结果:

说白了,super就是为了方便子类调用父类的构造方法。

5.6 final关键字 

final可修饰:①类②成员变量③方法中的局部变量

final class A {
    …
}

final类

“没儿子,断子绝孙了”

final方法

父类中的final方法,子类中老老实实继承,不能重写。

“就像传家宝,你总不能卖了买其他的吧。”

final修饰变量

final修饰的常量就是常量,和C中差不多,定义时就要赋值,且之后不能被改变。

final double PI = 3.1415926;

  • 37
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值