2

这是场景: -

class Canine{
  public void roam(){
    System.out.println("Canine-Roam");
  }
}

public interface Pet{    
  public abstract void roam();
}


class Dog extends Canine implements Pet{

  public void roam(){
    System.out.println("Dog Roam");
  }
  public static void main(String [] args){
    Dog adog = new Dog();
    adog.roam();
  }
}

我知道 JVM 在选择运行哪个方法时不能有任何混淆,这意味着哪个方法会被覆盖。但无论如何我都很困惑。为什么这个程序会编译?

4

4 回答 4

8

否 - 同一个方法不能在一个类中存在两次。

接口只是声明了一个类实现特定方法的要求。它实际上并没有创建该方法。

因此,通过继承获得方法实现的类定义了该方法。这个(单个)实现满足接口的要求。

在你的情况下:

  1. Dogextends Canine,所以这意味着roam()方法 fromCanine是可用的,如果不被覆盖,它将作为 Dog 对象上的方法公开。
  2. 但随后Dog用自己的定义覆盖roam()超类的方法。这是允许的,并且仍然只有一个明确的方法被调用roam()-Dog新的覆盖。
  3. Dogimplements Pet,这意味着它需要有一个roam()方法。确实如此 - 因此它是此接口的有效实现。
于 2012-10-26T10:17:57.070 回答
2

你的情况很好,它会运行良好并输出Dog Roam。这意味着Dog类中的函数运行。

您没有收到任何编译时错误,因为 Dog 中的方法正在实现接口中声明的抽象方法,并且巧合的是该方法的方法签名与父类匹配。

于 2012-10-26T10:20:21.983 回答
1

我认为你混淆了两件事:

  • 实施:做了什么?见:Canine.roam()Dog.roam()
  • 接口:你如何调用它?看:Pet.roam()

很明显,您roam()在两个类中有两个“实现”:

  • Canine.roam()
  • Dog.roam()

同一个类中永远不会有两个相同的方法。

而且因为Dogextends Canine,该方法Canine.roam()被覆盖了。您的main()函数改为使用 Dog.roam()

于 2012-10-26T10:31:02.293 回答
0

您已经为 Dog 类型创建了对象并将其分配给 Dog 引用类型。
压倒一切,与这里无关。尽管您从犬类扩展了 Dog 类,但两者都是 2 种不同的类型。
在编译时,编译器检查方法定义是否存在于引用类型中。而已。它必须在那里。在运行时,JVM 首先检查引用类型中的方法,然后它发现“引用类型的”子类中是否存在相同方法的任何覆盖版本。
如果存在,它将被执行。否则,将执行引用类型的方法。

IE

Canine c=new Dog(); 

将执行 Dog 的方法。

于 2012-10-26T11:06:33.040 回答