java多态之如何确定调用方法

java多态之如何确定调用方法

多态的方法调用确认,第一要确认方法签名,第二要确认调用谁的方法

确认方法签名

确认方法签名有一个规则:
this.show(object)->super.show(object)->this.show(super(object))->super.show(super(object))

首先,要明确一点,一个对象有哪些方法,是由声明的类型决定,而不是实例化的类型决定;所以,规则里面的this指的是声明类型的类;所以

  1. 先在声明类中寻找方法名一致,参数一致的方法;
  2. 如果没找到,就在声明类的父类中寻找方法名一致,参数一致的方法;
  3. 如果没找到,就在声明类中寻找方法名一致,形参是入参父类的方法;
  4. 如果没找到,就在声明类的父类中寻找方法名一致,,形参是入参父类的方法;

这样,就能确定方法的签名

确认调用谁的方法

决定了调用谁的成员方法,是根据被实例化的类型而不声明的类型。所以在第一步确认了方法签名之后,需要在实例化类中寻找方法签名一致的方法,如果有则确认调用该方法,如果不存在,则在父类中寻找。按照此逻辑,直到找到方法签名一致的方法;

练习

public class Test {
    public static void main(String[] args) {
        A a1 = new A();
        B b = new B();
        System.out.println(a1.show(b));
    }
}

class A {
    public String show(A obj) {
        return ("A and A");
    }
}

class B extends A {
    public String show(B obj) {
        return ("B and B");
    }

    public String show(A obj) {
        return ("B and A");
    }
}

上面的的题目中,我们根据步骤来判断调用的哪个方法:

  1. 先在声明类中寻找方法名一致,参数一致的方法; 不存在
  2. 如果没找到,就在声明类的父类中寻找方法名一致,参数一致的方法; 不存在
  3. 如果没找到,就在声明类中寻找方法名一致,形参是入参父类的方法; show(A obj)
  4. 如果没找到,就在声明类的父类中寻找方法名一致,,形参是入参父类的方法;
  5. 确定了方法签名,则在实例化的类型中寻找show(A obj)方法 存在

则main方法中调用的是B类中的show(A obj)方法

思考

在学习完上述内容之后,我脑海里崩出了一个想法,如果在下面这个规则中,

this.show(object)->super.show(object)->this.show(super(object))->super.show(super(object))

把参数改成两个,并且在第三步中,this类中提供了两个方法,this.show(super(object1),object2)和this.show(object1,super(object2)),那么会选择哪个方法来调用呢

我有两个猜想:

  1. 参数是有顺序的,按照参数的顺序寻找super,例如先
    1. this.show(super(object1),object2)
    2. this.show(object1,super(object2))
    3. this.show(super(object1),super(object2))
  2. 调用方法不确定,编译失败

简单的写代码尝试一下,声明A执行B,参数C和D是B的子类,然后按照上面猜想1的三种顺序实现三个方法,emmm,编译失败...

public class Test {
    public static void main(String[] args) {
        A a = new B();
        C c = new C();
        D d = new D();
        System.out.println(a.show(c, d));
    }
}

class A {
    public String show(B obj1, B obj2) {
        return ("A:B and B");
    }
    public String show(B obj1, D obj2) {
        return ("A:B and D");
    }
    public String show(C obj1, B obj2) {
        return ("A:C and B");
    }
}

class B extends A {
    public String show(B obj1, B obj2) {
        return ("B:B and B");
    }
    public String show(B obj1, D obj2) {
        return ("B:B and D");
    }
    public String show(C obj1, B obj2) {
        return ("B:C and B");
    }
}

class C extends B {
}

class D extends B {
}

posted on 2022-04-02 22:34  灰马非马  阅读(272)  评论(0编辑  收藏  举报

导航