【问题标题】:Why parent class method is getting called and not child class in this case?为什么在这种情况下调用父类方法而不是子类?
【发布时间】:2014-11-13 07:40:48
【问题描述】:

我有一个父类 A 和它的子类 B。两者都有 doSomething 方法,参数类型不同。

A类

package Inheritance;

public class A {

    public void doSomething(Object str){
        System.out.println("Base impl:"+str);
    }
}

B类

package Inheritance;

public class B extends A{

    public void doSomething(String str){
        System.out.println("Child impl:"+str);
    }

    public static void main(String[] args) {

        A a = new B();
        a.doSomething("override");

    }
}

当我运行它时,我得到“Base impl:override”作为输出!

a指向了B的一个对象,而他传递的参数是String,那么不应该调用BdoSomething(String str)方法吗?

【问题讨论】:

    标签: java inheritance


    【解决方案1】:

    当您使用类型 A 的引用时,您只能看到为类 A 定义的方法。由于 B 中的 doSomething 不会覆盖 A 中的 doSomething(因为它具有不同的签名),所以它不是调用。

    如果您要使用 B 类型的引用,这两种方法都可用,并且会选择 B 的 doSomething,因为它有一个更具体的参数(字符串与对象)。

    【讨论】:

    • 你的意思是当我这样做时:'A a = new B();' 'a.doSomething("覆盖");'第一个编译器将检查 A 类的 doSomething(String) 并且它不存在!然后发现A有doSomething(Object),由于B类中doSomething(Object)没有被覆盖,所以调用了父类的doSomething(Object)。我说的对吗?
    • @PraveeshP 是的。 doSomething(Object) 是 A 中唯一与调用 a.doSomething("override") 匹配的方法
    • 这意味着每当我做'ParentClass obj = new ChildClass();'并使用 obj 调用任何方法,编译器将首先在 ParentClass 中检查该方法,因为 obj 是 Parent 类型。如果找到,它将检查 ChildClass 是否已覆盖相同的内容。那是流量吗?
    • @PraveeshP 差不多。编译器会在 ParentClass 中找到最适合方法调用参数的方法。如果找不到,则代码将无法编译。只有在运行时,JVM 才会检查 obj 实例的实际类型,并根据该类型调用 ChildClass 方法,如果它覆盖了 ParentClass 方法。
    【解决方案2】:

    我猜这不被认为是方法覆盖的情况,因为签名并不完全相同。在 B 中将 String 参数更改为 Object。

    【讨论】:

      【解决方案3】:

      在类 A 中,您声明了一个方法 doSomething(Object obj)。但是,在 B 类中,您声明了方法 doSomething(String str),它的参数类型与 A 类中的不同。这意味着 B 类的 doSomething 不会覆盖 A 类的 doSomething

      要获得所需的输出,请执行以下操作(我省略了主要方法以获得更通用的代码示例):

      public class A {
          public void doSomething(Object str){
              System.out.println("Base impl:"+str);
          }
      }
      
      public class B extends A {
          // Helpful annotation: It tells you
          // if you aren't overriding any known method
          @Override
          public void doSomething(Object str) {
              System.out.println("Child impl:"+str);
          }
      }
      

      【讨论】:

        【解决方案4】:

        正如@Eran 所说

        当您使用 A 类型的引用时,您只会看到为 A 类定义的方法。由于 B 中的 doSomething 不会覆盖 A 中的 doSomething(因为它具有不同的签名),因此不会调用它.

        如果你想调用 B 中定义的方法,你需要将它转换为如下

        ((B)a).doSomething("override");
        

        或者你必须隐式使用 B 的实例

        【讨论】:

          猜你喜欢
          • 2014-03-24
          • 2018-07-03
          • 2017-05-17
          • 2014-01-22
          • 2017-06-11
          • 2021-08-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多