5

在查看一些 OOP 资料时,我想到了一个让我有点困惑的问题:

考虑具有以下接口、抽象类和具体类:

package one;

public interface A {

    void doStuff();
}

package one;


public abstract class B implements A {

    public abstract void doStuff();


}

class C extends B{


    public void doStuff() {

    }
 }

C类不会编译,除非它提供了 method 的实现doStuff()。这里的问题:

1-doStuff()C中的方法是接口A的方法的实现,还是用于类B中的抽象方法?更具体地说:JVM如何将函数视为接口或抽象类的调用函数?

2-doStuff()抽象类BdoStuff()中的抽象方法是否被认为是接口A中方法的“实现” ?所以这使得C类必须实现抽象类的版本doStuff()而不是接口的?

4

5 回答 5

4

对于问题 #1:类 C 中的 doStuff 方法是对 B 和 C 的 doStuff 方法声明的实现。因为抽象类 B 和接口 A 中的 doStuff 方法声明具有彼此相同的签名。实际上,如果 B 实现了 C,则不需要再次声明 doStuff 方法。

对于问题 #2:不,B 中的 doStuff 只是一个声明,而不是方法实现。如果B没有方法实现或额外的方法声明,则不需要B类。抽象类基本上是一种包含高级逻辑的模板,以方便其子类。

于 2013-03-04T13:33:49.110 回答
1

例如 B 类,C.doStuff() 覆盖 B.doStuff() 并实现 A.doStuff()。java中的所有方法都是虚拟调用的。事实上,对于用户来说,C.doStuff() 是否覆盖 B 的方法或 A 的方法是没有区别的。对于 jvm,它会有所不同,因为基于接口的调用与基于类的调用不同。

UPD:这取决于您从中调用的链接类型。javac会生成不同的opcode:invokevirtualinvokeinterface

于 2013-03-04T13:45:09.983 回答
1

在一个接口中,所有方法都是publicand abstract

知道了这一点,接口A的doStuff其实 public abstract void doStuff()就是. 这应该看起来很熟悉,因为抽象类 B 具有相同的方法签名。

回答问题 1,B 类doStuff()与接口 A相同doStuff()。由于 Java 中的所有方法都是虚拟doStuff()的,因此无论您的 C 被声明为 A、B 还是 C ,调用都是相同的。

至于问题2,没有。BdoStuff()是冗余代码,实际上并没有做任何事情。doStuff()无论 B 是否声明, C 都在执行doStuff()A。

于 2013-03-21T18:21:06.617 回答
0

如果您删除

 public abstract void doStuff();

在你的抽象类中,继承这个类的孩子必须实现这个方法。

尝试在 B 类中删除此方法,并在 C 类中查看结果

请参阅http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html中的抽象类实现接口部分

于 2013-03-04T13:08:00.743 回答
0

我认为您正在寻找的解释可以在这里找到。

问题 1:C 类中的方法实现了两者。但是由于它只扩展了 B,它只需要实现 B 抽象方法和未实现的接口。

问题2:它不被认为是一种实现。抽象类不必实现所有接口方法。C 类中的实现是强制性的(即使 B 类中没有抽象类)。

于 2013-03-04T13:40:52.450 回答