1,多态通过分离做什么和怎么做,从另一个角度将接口和实现分离开来。
2,向上转型(upcasting)
将某个对象的引用视为对其基类的引用的做法叫向上转型。
3,前期绑定和后期绑定(动态绑定)
将一个方法调用和一个方法的主体关联起来被称作绑定,若在程序执行前进行绑定(如果有的话,由编译器和连接程序实
现),叫前期绑定。
在运行时根据对象的类型进行绑定,叫后期绑定,也叫动态绑定。
java中除了static方法和final方法(private方法属于final方法)之外,其他的所有方法都是后期绑定,我们不必判定是否
应该进行后期绑定,它会自动发生。
一旦知道了java程序所有方法都是通过定态绑定之后,我们就可以编写只与基类打交道的程序代码了,并且这些代码对于
所有的导出类都可以正确运行。
public class Shape {
public void draw() {}
public void erase() {}
} ///:~
public class Circle extends Shape {
public void draw() { print("Circle.draw()"); }
public void erase() { print("Circle.erase()"); }
} ///:~
public class Square extends Shape {
public void draw() { print("Square.draw()"); }
public void erase() { print("Square.erase()"); }
} ///:~
public class Triangle extends Shape {
public void draw() { print("Triangle.draw()"); }
public void erase() { print("Triangle.erase()"); }
} ///:~
public class RandomShapeGenerator {
private Random rand = new Random(47);
public Shape next() {
switch(rand.nextInt(3)) {
default:
case 0: return new Circle();
case 1: return new Square();
case 2: return new Triangle();
}
}
} ///:~
public class Shapes {
private static RandomShapeGenerator gen = new RandomShapeGenerator();
public static void main(String[] args)
{
Shape[] s= new Shape[9];
for ( int i=0;i<s.length;i++)
{
s[i] = gen.next();
}
for (Shape shp :s)
{
shp.draw();
}
}
}
运行的结果是:
Triangle.draw()
Triangle.draw()
Square.draw()
Triangle.draw()
Square.draw()
Triangle.draw()
Square.draw()
Triangle.draw()
Circle.draw()
4,“覆盖”私有方法
public class PrivateOverride {
private void f() { print("private f()"); }
public static void main(String[] args) {
PrivateOverride po = new Derived();
po.f();
}
}
class Derived extends PrivateOverride {
public void f() { print("public f()"); }
} /* Output:
编译器不会报错,但是导出类的f()方法是一个新的方法,不会覆盖基类的f()方法。
5,构造器是隐含的static方法。
6,协变返回类型
jdk5中添加了协变返回类型,表示在导出类中的被覆盖方法可以返回基类方法的返回类型的某种导出类。
class Grain {
public String toString() { return "Grain"; }
}
class Wheat extends Grain {
public String toString() { return "Wheat"; }
}
class Mill {
Grain process() { return new Grain(); }
}
class WheatMill extends Mill {
Wheat process() { return new Wheat(); }
}
public class CovariantReturn {
public static void main(String[] args) {
Mill m = new Mill();
Grain g = m.process();
System.out.println(g);
m = new WheatMill();
g = m.process();
System.out.println(g);
}
} /* Output:
7,向下转型和运行时类型识别
向上转型会丢失具体的类型信息,向下转型应该能获得类型信息。在c++中,必须执行一个特殊的操作才能获得安全的向下
类型。java所有转型都会得到检查!运行时会检查,以保证它却确实是我们希望的类型,否则,抛出
ClassCastException(类型转换异常)。这种在运行时对类型进行检查的行为称为“运行时类型识别”(RTTI)。
class Useful {
public void f() {}
public void g() {}
}
class MoreUseful extends Useful {
public void f() {}
public void g() {}
public void u() {}
public void v() {}
public void w() {}
}
public class RTTI {
public static void main(String[] args) {
Useful[] x = {
new Useful(),
new MoreUseful()
};
x[0].f();
x[1].g();
// Compile time: method not found in Useful:
// x[1].u();
((MoreUseful)x[1]).u(); // Downcast/RTTI
// ((MoreUseful)x[0]).u(); // Exception thrown
}
} ///:~