1. 定义子类
    $$关键字extends$$

    • C++注释:Java与C++定义继承的方式十分相似,Java用关键字extends代替C++中的冒号(:),在Java中,所有的继承都是公有继承,而没有C++中的私有继承和保护继承

    • 关键字extends表明正在构造的新生类派生于一个已经存在的类。

      • 已存在的类称:
        • 超类(superclass)
        • 基类(base class)
        • 父类(parent class)
      • 新生类称:
        • 子类(subclass)
        • 派生类(derived class)
        • 孩子类(child class)
    • 子类自动继承超类中的方法,设计时应将通用的方法放在超类,而将具有特殊用途的方法放在子类

  2. 覆盖方法

    • 超类的某些方法在子类中不适合用,那么就要在子类提供这种方法的重载版本

    • 子类继承拥有超类的域,但子类内的方法不能直接访问超类私有域,必须借助公有的接口

    • 由于Manager类的构造器不能访问Employee类的私有域,所以必须利用Employee类的构造器对这部分私有域进行初始化,可以通过super实现对超类构造器的使用。

    • 使用super调用构造器的语句必须是子类构造器的第一条语句

    • 如果子类的构造器没有显示地调用超类地构造器,则将自动地调用超类默认(没有参数)的构造器,如果超类没有不带参数的构造器,并且在子类的构造器中又没有显示地调用超类地其他构造器,则Java编译器将报告错误。

    • C++注释:
      $$在C++地构造函数中,使用初始化列表语法调用\超类地构造器,而不调用super $$

      1
      2
      3
      4
      Manager::Manager(String name,double salary,int year,int month,int day):Employee(name,salary,year,month,day)
      {
      bonus=0;
      }
  3. 调用
    $$e.getSalary();$$

    • e可以的声明为超类Employee类型,但实际上e既可以引用Employee类型对象,也可以引用Manager类型对象

    • 当e引用Employee对象时,e.getSalary)调用Employee类中地getSalary方法;
      当e引用Manager对象时,e.getSalary)调用Manager类中地getSalary方法;
      虚拟机直到e实际引用地对象类型,因此能够正确地调用相应地方法。

  1. 多态(polymorphism)
    $$一个对象变量(例如,变量e)可以指示多种实际类型的现象\被称为多态$$

    • $$动态绑定(dynamic binding)$$
      在运行时能够自动地选择调用哪个方法的现象

    • 用”is-a”规则,它表明子类的每个对象也是超类的对象

      • is-a规则的另一种表述法是置换规则。它表明程序中出现超类的任何地方都可以用子类对象置换
        • 例如,可以将一个子类的对象赋值给超类对象

          Manager boss=new Manager(...);
          Employee[] staff=new Employee[3];
          staff[0]=boss;
          boss.setBonus(5000);//OK
          staff[0].setBouns(5000);//ERROR
          变量staff[0]与boss引用同一个对象。但编译器将staff[0]看成Employee对象.
          不能将一个超类的引用赋给子类的变量
    • C++注释:
      在Java中,不需要将方法声明为虚拟方法。动态绑定是默认的处理方式,如果不希望一个方法具有虚拟的特征,可以将它标记为final

    • $$警告$$
      在Java中,子类数组的引用可以转换成超类数组的引用,而不需要采用强制类型转换

      例如,下面是一个经理数组

      Manager[] managers=new Mabager[10];

      将它转换成Elmpoyee[]完全是合法的;

      Employee[] staff=managers;

      这样做肯定不会有问题,毕竟,如果是一个Manager[i]是一个Manager,也一定是Employee,然而,实际上,将会发生一些令人惊讶的事情。要切记managers和staff引用的是同一个数组。

      staff[0] = new Employee("Harry Hacker",...);

      编译器竟然接纳了这个赋值操作,但在这里,staff[0]与maagers[0]引用的是同一个对象,似乎我们把一个普通雇员擅自归入经理队列。这是一种糟糕发生的情况,当调用managers[0].setBonus(1000)的时候,将会导致调用一个不存在的实例域,进而搅乱相邻存储空间的内容。
      为了确保不发生这类的错误,所有数组都要牢记创建它们的元素类型,并负责监督仅将类型兼容的引用存储到数组中,例如,使用new Managers[10]创建的数组是一个经理数组。
      如果试图存储一个Employee类型的引用就会引发ArrayStoreException异常
  2. 继承层次
    $$继承并不限于一个层次$$

    • 派生类出来的所有类的集合被称为继承层次(inheritance hierarchy).
      在继承层次中,从某个特定的类型到其祖先的路径被称为该类的继承链(inheritance chain)

    • 注意:

      • Java不支持多态。有关Java中多继承的实现方式,需要用到接口