• 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 {
    }
    

  • 相关阅读:
    前后端分类状态下SpringSecurity的玩法
    拓展 centos 7
    linux 日志管理
    Linux 内存监控
    Linux 周期任务
    Linux 文件系统
    linux 磁盘管理
    图论 最短路总结
    进阶线段树之乘法操作
    暑假集训Day 10 小烈送菜
  • 原文地址:https://www.cnblogs.com/yanghanwen/p/16094594.html
Copyright © 2020-2023  润新知