多态也称作动态绑定、后期绑定或运行时绑定。
方法调用绑定
将一个方法调用同一个方法主体关联起来被称作绑定。若在程序执行前进行绑定,叫做前期绑定。在运行时根据对象的类型进行绑定叫做后期绑定。后期绑定也叫做动态绑定或运行时绑定。
Java中除了static
方法和final
方法(private
方法属于final
方法)之外,其他所有的方法都是后期绑定。
缺陷:“覆盖”私有方法
只有非private
方法才可以被覆盖;但是还需要密切注意覆盖private
方法的现象,这时虽然编译器不会报错,但是也不会按照我们所期望的来执行。确切地说,在导出类(子类)中,对于基类中的private
方法,最好采用不同的名字。
1 | public class PrivateOverride { |
缺陷: 域与静态方法
任何域访问操作都将由编译器解析,因此不是多态的。
1 | class Super { |
只有普通的方法调用可以是多态的,如果某个方法是静态的,它的行为就不具有多态性。
1 | class StaticSuper { |
构造器内部的多态方法的行为
在一般的方法内部,动态绑定的调用是在运行时才决定的,因此对象无法知道它是属于方法所在的那个类,还是属于那个类的导出类。
如果要调用构造器内部的一个动态绑定方法,就要用到那个方法的被覆盖后的定义。
1 | class Glyph { |
编写构造器时有一条有效的准则:“用尽可能简单的方法使对象进入正常状态;如果可以的话,避免调用其他方法”。
在构造器内唯一能够安全调用的那些方法是基类中的final
方法(也适用于private
方法,它们自动属于final
方法)。这些方法不能被覆盖,因此也就不会出现令人惊讶的问题。
协变返回类型
协变返回类型指的是子类中的成员函数的返回值类型不必严格等同于父类中被重写的成员函数的返回值类型,而可以是更 “狭窄” 的类型。
Java 5.0添加了对协变返回类型的支持,即子类覆盖基类方法时,返回的类型可以是基类方法返回类型的子类。协变返回类型允许返回更为具体的类型。
1 | class Grain { |