为什么多态性不适用于Java中的重载方法



我对Java中方法重写和重载的工作原理有基本的了解。但我的问题是,为什么编译器会根据参数的编译类型来搜索最具体的方法?换句话说,在方法重载的情况下,为什么它会根据引用的类型而不是对象的类型进行搜索?

检查以下示例

class Base { }
class Derived extends Base { }
class Test {
    void foo(Base thing) { System.out.println("foo(Base)"); }
    void foo(Derived thing) { System.out.println("foo(Derived)"); }
    public static void main(String[] args) { 
        Test tester = new Test(); 
        Base base = new Base(); 
        tester.foo(base);// 1st call 
        base = new Derived(); 
        tester.foo(base); // 2nd call
        tester.foo(new Derived()); // 3rd call
    } 
}

实际输出

1st call: foo(Base)
2nd call: foo(Base)
3rd call: foo(Derived)

输出我期待

1st call: foo(Base)
2nd call: foo(Derived)
3rd call: foo(Derived)

1)编译时发生重载,即要定义哪个方法执行是在编译时决定的
2) 您正在将派生类对象引用指定给基类对象
3) 因此,在编译时显然不知道哪个引用了您的基类对象将来将具有,即在运行时
4) 这就是编译器查看中引用类型的原因方法重载的情况

您必须记住,当您定义一个变量类型(如Bass)时,它只能存储自身的值和从自身派生的类(如Derived)。

一旦为该变量分配了变量类型,就不能对其进行更改。

一种想法:

假设您的Bass类存储一个字段值:

class Bass {
String field1;
}

假设您的Derived类存储了一个附加字段"

class Derived extends Bass {
String field2;
}

现在假设您创建一个低音实例:

Bass bass = new Base();

您可以从对象中访问field1值。

现在你说你做以下事情:

bass = new Derived();

您仍然可以从对象访问field1值。但是,您无法访问field2值,因为低音实例不存储此值。它不符合其结构。

我希望这能帮助您理解为什么当将变量类型设置为其派生类时,它不会更改原始变量类型。

最新更新