继承的基本思想是,可以基于已有的类创建新的类。继承已存在的类就是复用(继承)这些类的方法,而且增加一些新的方法和字段,使心嘞能够使用新的情况。
1.定义子类
Java使用extengs 表示继承。
在Java中,所有的继承都是公共继承,而没有C++中的私有继承和保护继承。
关键字extends 表明正在构造的新类派生于一个已存在的类。这个类称为超类、基类或父类;新类称为子类、派生类或孩子类。
通过扩展超类定义子类的时候,只需要指出子类与超类的不同之处。在设计类的时候,应该将最一般的方法放在超类中,而将更特殊的方法放在子类中。
2. 覆盖方法
public class Employee {
private double salary;
public double getSalary() {
return salary;
}
}
public class Manager extends Employee {
private double bonus;
public double getSalary() {
double baseSalary = super.getSalary();
return baseSalary + bonus;
}
}
子类调用父类的方法需要使用关键字super 。
注:在Java中使用关键字super 调用超类的方法,而在C++中则采用超类名加:: 操作符的形式。 有些人认为super 与this 引用是类似的概念,实际上,这样比较并不太恰当。这是应为super 不是一个对象的引用,例如不能将值super 赋值给另一个对象变量,它只是一个指示编译器用超类方法的特殊关键字。
继承绝对不会删除任何字段或方法。
3.子类构造器
由于子类的构造器不能访问父类的私有字段,所以必须通过一个构造器来初始化这些私有字段。可以利用特殊的super 语法调用这个构造器。使用super 调用构造器必须是子类构造器的第一条语句。
如果子类没有显式地调用超类地构造器,将自动地调用超类地无参数构造器。如果超累没有无参数地构造器,并且在子类地构造器中有没有显式地调用超类地其他构造器,Java编译器就会报告一个错误。
回想一下,关键字this 有两个含义:一是指示隐式参数地引用,二是调用该类地其他构造器。 类似地,super 关键字也有两个含义:一是调用超类地方法,二是调用超类的构造器。调用构造器的语句只能作为另一个构造器的第一条语句出现。构造器参数可以传递给当前类(this )的另一个构造器,也可以传递给超类(super )的构造器。
一个对象变量可以指示多种实际类型的现象称为多态。 在运行时能够自动地选择适当地方法,称为动态绑定。
4.继承层次
继承并不仅限于一个层次。 有一个公共超类派生出来地所有类地集合称为继承层次。 在继承层次中,从某个特定的类到其祖先的路径称为该类的继承链。 通常,一个祖先类可以有多个子孙链。
Jabalpur不支持多重继承,但提供了一些类似多重继承的功能——接口。
5.多态
有一个简单规则可以用来判断是否应该将数据设计为继承关系,这就是“is-a”规则,它指出子类的每个对象也是超类的对象。 “is-a”规则的另一种表述是替换原则。它指出程序中出现超类对象的任何地方都可以使用子类对象替换。 在Java程序中,对象变量是多态的。 不能将超类的引用赋值给子类变量。
警告:在Java中,子类引用的数组可以转换成超类引用的数组,而不需要使用枪支类型转换。 所有数组都要牢记创建时的元素类型,并负责监督仅将类型兼容的引用存储到数组中。
6.理解方法调用
下面是方法调用过程的详细描述:
- 1)编译器查看对象的声明类型和方法名。需要注意的是:有可能存在多个名字为
f 但 参数类型不一样的方法。 - 2)接下来,编译器确定方法调用中提供的参数类型。如果在所有名为
f 的方法中存在一个与所提供参数类型完全匹配的方法,就选择这个方法。这个过程称为重载解析。如果编译器没有找到与参数类型匹配的方法,或者发现经过类型转换后有多个方法与之匹配,编译器就会报告一个错误。 - 3)如果是private方法、static方法、final方法或者构造器,那么编译器将可以准确地知道应该调用哪个方法。这成为静态绑定。与此对应的是,如果要调用的方法依赖于隐式参数的实际类型,那么必须在运行时使用动态绑定。
- 4)程序运行并且采用该动态绑定调用方法时,虚拟机必须调用与参数所引用对象的实际类型对应的那个方法。
每次调用方法都要完成这个搜索,世界开销相当大。因此,虚拟机预先为每个类计算了一个方法表,其中列出了所有方法的签名和调用的实际方法。
在覆盖一个方法的时候,子类方法不能低于超类方法的可见性。特别是,如果超类方法是public,子类方法必须也要声明为public。
7.阻止继承:final类和方法
不允许扩展的类称为final类。 对于final字段来说,构造对象之后就不允许改变它们的值了。不过,如果将一个类声明为final,只有其中的方法自动地称为final,而不包括字段。
将方法或类声明为final地主要原因是:确保它们不会在子类中改变语义。
如果一个方法没有被覆盖并且很短,编译器能够对它进行优化处理,这个过程称为内联。
|