不要谈论理论,而是让我直接跳到示例来演示我想要问的内容。
// The below piece of code is present in a single java file named "MyMain.java"
public class MyMain {
public static void main(String args[]) {
IFace iFace = new CSub();
iFace.method(); // This method essentially belongs to CSuper which doesn't implement IFace
}
}
interface IFace {
void method(); // Method in the interface
}
class CSuper {
public void method(){ // some method in this class, but not the one which implements the method of IFace
System.out.println("I'm not implementing IFace's method");
}
}
class CSub extends CSuper implements IFace {} // No method implemented in the class and yet no error.
显然上面的代码工作正常,因为我能够获得输出我没有在执行时实现IFace的方法。
我的问题是,CSub
如何将method()
CSUper
作为method()
IFace
接口的实现。似乎继承是这背后的一个,但我需要一些具体的答案。还有,这是否有一个JLS参考,可以通过继承来阐明这是如何实现的?
这个问题的后续问题就是说,有一些原因可以解决这个问题(因为我猜它是继承但需要确定它),为什么不相同的代码片段工作如果我做以下任何一项变化?
更改1:
class CSuper {
void method(){ // there is no access specifier, thus default(package)
System.out.println("I'm not implementing IFace's method");
}
}
更改2:
class CSuper {
protected void method(){ // access specifier is now protected
System.out.println("I'm not implementing IFace's method");
}
}
对于上述两个更改,我收到一个编译错误,说明继承的方法CSUper.method()可以在此行中隐藏IFace 中的公共抽象方法
class CSub extends CSuper implements IFace {}
为什么会这样?由于它是继承,protected
和默认访问说明符都应该有效,因为所有类都存在于同一个文件中。并且method()
必须已继承到CSub
类,就像它在问题的第一部分中所做的那样。任何人都可以突出这个案例吗?
答案 0 :(得分:4)
除非声明的类是抽象的,否则每个直接超接口的所有方法成员的声明必须通过此类中的声明或从直接超类继承的现有方法声明来实现 ,因为不允许抽象方法的类(第8.1.1.1节)。
答案 1 :(得分:2)
第1部分的答案非常简单 - 接口只需要接口所属的类实现具有该签名的方法。
它并不关心实际定义方法的位置 - 只要它存在,那么接口就是有效的。
原因也很明显。所有接口都说是“具有此接口的任何对象,您可以使用参数Y调用名为X的函数,它将返回Z”。通过从超类继承该方法,您将满足该要求。
这也回答了第2部分。要实现接口,实现方法必须是公共的 - 所以任何人都可以访问它。
通过使超类方法包成为私有或受保护,它不再符合要求。
class CSub extends CSuper implements IFace {
public method() {
super.method();
}
}
通过这样做你可以使方法公开(允许通过继承使访问更广泛,你不能让事情更加受限制),现在它将再次满足界面。
访问限制是方法签名的一部分。解释为什么要考虑一个班级IFace x
。然后,他们将尝试调用接口中定义的x.method()
。
如果他们与您的实施不在同一个包中,他们仍然需要能够拨打x.method()
。因为x.method()
必须公开以满足界面 - 否则人们可以获得IFace
,但该方法将无法使用。