【问题标题】:Java Inheritance: Why is it not calling the method of the subclass?Java继承:为什么不调用子类的方法?
【发布时间】:2019-01-25 12:17:37
【问题描述】:

我想知道为什么 Java 使用 mA() 方法而不是 im(b) 方法调用子类方法。 我真的看不出它这样做的任何原因。 Java 如何决定调用哪个方法?

public class C {
    public static void main(String[] args) {
        A a = new B();
        B b = new B();

        a.mA();  // prints BmA
        a.im(b);  // prints Aim  --  Why not Bim?
        b.im(a);  // prints Aim  -- Why not Bim?
    }
}


public class A {
    public void mA() {System.out.println("AmA");};
    public void im(A a) {System.out.println("Aim");};
}


public class B extends A {
    public void mA() {System.out.println("BmA");};
    public void im(B b) {System.out.println("Bim");};
}

我希望 im(b) 的行为类似于 mA()。

【问题讨论】:

  • ehm ... 不,如果要调用 im(B b),则需要在声明为 B 元素的变量上调用它。 a 可能被实例化为一个,但它仍然被声明为 A 的一个元素
  • @Stultuske 是的,我知道,但我想知道如果我将 Java 声明为 B,为什么会这样做。
  • @DanielF.M.因为在那里你传递了一个 A,而在 B 中的方法中,你期望 B 类型之一。你没有重写,而是重载了你的方法
  • @Lino 为什么 b.im(a) 不打印'Bim'呢? Java 知道 A a 是 B 的一个实例,因此我希望 b.im(a) 打印 'Bim'。
  • @DanielF.M.因为该方法需要一个 B 的实例作为参数,但您传递了一个 A 的实例

标签: java inheritance overloading


【解决方案1】:

编译器不知道它是B 的一个实例,因此它不知道B.im(B) 是在那里调用的候选对象。

它确实知道它是A 的一个实例,并且有一个名为im 的方法,它接受A 类型的单个参数;因为B 也是A 的一个实例,所以这就是它调用的方法。

【讨论】:

  • 它知道 mA()。为什么不能假设它也知道 im(b)?
  • A 上有一个名为mA 的方法,它不带参数;并且B.mA() 覆盖A.mA(),因此调用了子类方法。 B.im(B) 不会覆盖A.im(A),因为参数类型不同。
【解决方案2】:

这是因为参数类型。

im(B b) 不会覆盖 im(A a)

见:https://www.programcreek.com/2009/02/overriding-and-overloading-in-java-with-examples/

【讨论】:

    【解决方案3】:

    方法 im(A) 和 im(B) 不是重写等效的。如果您尝试使用 @Override 注释 im(B),您将收到编译器错误。只有具有相同签名的方法是等效的。方法的签名由名称和参数类型组成。您的示例中的参数类型是不同的,即使 B 继承了 A。

    如果你想实现这一点,你可以将参数类型更改为Object,它的缺点是它不是类型安全的。对于类型安全的解决方案,您必须使用泛型。

    【讨论】:

    • 在 JLS 的措辞中,要求它必须是一个子签名,参见8.4.8.1. Overriding (by Instance Methods):“mC 的签名是一个子签名(第 8.4 节)。 2) mA 的签名。”
    • @Hulk 您只能覆盖具有完全相同签名的方法。您唯一可以更改的是返回类型,但前提是它是子类型。我看不出有什么问题。
    • 您可以更改的另一件事是参数的通用类型 - 它们只需要具有相同的擦除(我承认这与这里无关)。我只是在挑剔,这是一个很好的答案(已经投票)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-17
    • 2019-10-21
    • 1970-01-01
    相关资源
    最近更新 更多