封装通过合并特征和行为来创建新的数据类型,“实现隐藏”通过将细节“私有化”把接口和实现分离出来。多态通过分离“做什么”和“怎么做”将接口与实现分离出来。
多态方法的实现
第一个条件
我们知道类的继承,导出类可以覆盖基类的方法。
第二个条件
Java支持向上转型和动态绑定,所谓动态绑定就是Java程序在运行的时候能够自动地判断对象的类型,从而根据对象的类型而调用正确地方法(此方法必须是导出类覆盖的方法,而不是导出类的扩展方法) 。
所以
所以Java程序由于向上转型和动态绑定只需要操作基类对象就可以对每一个不同的导出类而实现相应的方法。
注意:Java中static方法和final方法(private方法属于final方法)不支持后期绑定。因为static和final方法均不能被覆盖。
class Shape{
void draw();
}
class Circle extends Shape{
void draw(){
System.out.println("Draw a Circle");
}
}
class Triangle extends Shape{
void draw(){
System.out.println("Draw a Triangle");
}
}
public class Shapes{
public static void main(String[] args){
Shape[] x = {
new Circle();
new Triangle();
}
x[0].draw();
x[1].draw();
}
}
/*控制台输出
Draw a Circle
Draw a Triangle
*/
抽象类和抽象方法
多态方法的实现是建立在导出类继承时覆盖基类的方法之上的。而在Java中可以通过关键字abstract来将一个方法声明成抽象方法(含有抽象方法的类是抽象类,无法创建实例),抽象方法仅有声明而无具体的实现代码。
构造器内部与多态方法
编写构造器的一条准则是:“用尽可能简单的方法使对象进入正常状态;如果可以的话,避免调用其他方法”。如果在构造器内调用某个方法,可能操作那个方法的对象还未被初始化,从而招致灾难!!!
在构造器内唯一能够安全调用的方法是基类中的final方法(也适用于private方法,因为它自动属于final方法),这些方法不会被覆盖,因此也就不会出现令人惊讶的问题。
向下转型
Java中所有的转型都会得到检查,以确保它是我们希望的那种类型,如果不是就会throw一个ClassCastException。这种在运行期间对类型进行检查的行为称作“运行时类型识别”(RTTI)。
class Shape{
void f();
}
class Circle extends Shape{
void f();
void u();
}
public class Shapes{
public static void main(String[] args){
Shape[] x = {
new Shape();
new Circle();
}
x[0].f();
x[1].f();
//! x[1].u();
((Circle)x[1]).u(); //DownCast/RTTI
((Circle)x[0]).u(); //Exception throw
}
}