常规的说法是这样的:
在调用一个方法时,先从本类中查找看是否有对应的方法,如果没有再到父类中查看,看是否从父类继承来。否则就要对参数进行转型,转成父类之后看是否有对应的方法。总的来说,方法调用的优先级为:
this.func(this)
super.func(this)
this.func(super)
super.func(super)
先验证一下二级继承是否成立:
A
|
B
假如调用这样的语句
A a = new A();
B b = new B();
b.fun(b);
检查的次序是这样的?
①、B中是否有方法fun(B b)?
②、A中是否有方法fun(B b)?
③、B 中是否有方法fun(A a)?
④、A 中是否有方法fun(A a)?
下面依次检验:
(一) ①>②?
class A{
public void fun(B b){
System.out.println("A.fun(B)");
}
}
class B extends A{
public void fun(B b){
System.out.println("B.fun(B)");
}
}
A a = new A();
B b = new B();
b.fun(b);//B.fun(B)
符合预测
(二) ②>③?
class A{
public void fun(B b){
System.out.println("A.fun(B)");
}
}
class B extends A{
public void fun(A a){
System.out.println("B.fun(A)");
}
}
public class OverrideTest {
public static void main(String []args){
A a = new A();
B b = new B();
b.fun(b);//A.fun(B)
}
}
符合预测
(三) ③>④?
class A{
public void fun(A a){
System.out.println("A.fun(A)");
}
}
class B extends A{
public void fun(A a){
System.out.println("B.fun(A)");
}
}
public class OverrideTest {
public static void main(String []args){
A a = new A();
B b = new B();
b.fun(b);//B.fun(A)
}
}
但是,以上说的是二级继承,但是在多级继承中又是怎样的情况呢?
多级继承
A
|
B
|
C
|
D
D d = new D();
d.fun(d);
先说结论:优先级是:
d.fun(( d )
c.fun( d )
b.fun( d )
a.fun( d )
d.fun( c )
c.fun( c )
b.fun( c )
a.fun( c )
d.fun( b )
c.fun( b )
b.fun( b )
a.fun( b )
d.fun( a )
c.fun( a )
b.fun( a )
a.fun( a )
按照前面验证的规律,应该是先检验如下两处
- D中是否有fun(D d)
- C中是否有fun(D d)
但是,假如以上两处检查不到,下一个应检查哪一条呢?是先检查D中的fun(C c),还是检查B中的fun(D d)?
class A{
}
class B extends A{
public void fun(D d){
System.out.println("B.fun(D)");
}
}
class C extends B{
}
class D extends C{
public void fun(C c){
System.out.println("D.fun(C)");
}
}
public class OverrideTest {
public static void main(String []args){
D d = new D();
d.fun(d);//B.fun(D)
}
}
检查完C中的fun(D d),就检查B中的fun(D d)
看到这里我忽然觉得:这和前面的:检查完D中的fun(D d)再检查C中的fun(D d)其实是一个意思。
是否可以这样理解:假如检查到C中的fun(D d),此时可以直接把c.fun(d)作为当前函数,再执行以下查找:
this.func(this)
super.func(this)
this.func(super)
super.func(super)
按照这个结论,检查完b.fun(d)就要检查a.fun(d)
class A{
public void fun(D d){
System.out.println("A.fun(D)");
}
}
class B extends A{
}
class C extends B{
}
class D extends C{
public void fun(C c){
System.out.println("D.fun(C)");
}
}
public class OverrideTest {
public static void main(String []args){
D d = new D();
d.fun(d);//A.fun(D)
}
}
证明了猜测
进而猜测d.fun(d)的检查顺序
d.fun(( d )
c.fun( d )
b.fun( d )
a.fun( d )
d.fun( c )
c.fun( c )
b.fun( c )
a.fun( c )
d.fun( b )
c.fun( b )
b.fun( b )
a.fun( b )
d.fun( a )
c.fun( a )
b.fun( a )
a.fun( a )
下面进行检查:
检查策略:先把所有的可能写上,那个方法被调用了,下一次就把这一个方法删掉,看下一次调用的是哪一个
class A{
public void fun(A a){
System.out.println("A.fun(A)");
}
public void fun(B b){
System.out.println("A.fun(B)");
}
public void fun(C c){
System.out.println("A.fun(C)");
}
public void fun(D d){
System.out.println("A.fun(D)");
}
}
class B extends A{
public void fun(A a){
System.out.println("B.fun(A)");
}
public void fun(B b){
System.out.println("B.fun(B)");
}
public void fun(C c){
System.out.println("B.fun(C)");
}
public void fun(D d){
System.out.println("B.fun(D)");
}
}
class C extends B{
public void fun(A a){
System.out.println("C.fun(A)");
}
public void fun(B b){
System.out.println("C.fun(B)");
}
public void fun(C c){
System.out.println("C.fun(C)");
}
public void fun(D d){
System.out.println("C.fun(D)");
}
}
class D extends C{
public void fun(A a){
System.out.println("D.fun(A)");
}
public void fun(B b){
System.out.println("D.fun(B)");
}
public void fun(C c){
System.out.println("D.fun(C)");
}
public void fun(D d){
System.out.println("D.fun(D)");
}
}
public class OverrideTest {
public static void main(String []args){
D d = new D();
d.fun(d);
}
}
结果证明了猜想