class A{
public String f(D obj){return ("A and D");}
public String f(A obj){return ("A and A");}
}
class B extends A{
public String f(B obj){return ("B and B");}
public String f(A obj){return ("B and A");}
}
class C extends B{}
class D extends B{}
class TestPoly{
public static void main(String[] args){
A a1 = new A();
A a2 = new B();
B b = new B();
C c = new C();
D d = new D();
/*
一、程序在编译的时候,编译器会根据类型找到个重装的方法;
二、运行的时候会根据实际类型找到覆盖之后的方法
*/
System.out.println(a1.f(b)); // A and A
/*
对a1调用f(b),a1是A类对象,
b对象的编译时类型是B,到A类中找方法,
只能对一个对象调用其编译时的类型定义的方法,
此时编译器会a1编译时类型A类中找方法,
到A类中找f(b),但A类中没有f(b),
所以要遵守向上就近匹配原则,没B类,找A类。
编译时绑定了“public String f(A obj){return (" A and A");}”
运行时,a1的实际类型就是A类型的,所以就找这个方法。
*/
System.out.println(a1.f(c)); //A and A
//同上面
System.out.println(a1.f(d)); //A and D
//这个直接找到
System.out.println(a2.f(b)); //B and A
/*
用b参数对a2调用f(b)方法,a2编译时类型是A,
在编译时找个方法,找f(B obj),但没找到,
所以只好找到A类中 f(A obj)
运行时,a2时运行时类型是B,运行时根据运行时类型找覆盖后的方法
B类运行有对A类中 f(A obj)这个方法的覆盖,
是B类中 f(A obj),所以输出“B and A”
*/
System.out.println(a2.f(c)); //B and A
//同上
System.out.println(a2.f(d)); //A and D
//这个直接找到
System.out.println(b.f(b)); //B and B
//直接找到
System.out.println(b.f(c)); //B and B
//C类型向上就近到B类型
System.out.println(b.f(d)); //A and D
/*
*/
}
}