扩展其他接口的默认方法和接口
Default methods and interfaces extending other interfaces
假设有两个接口 Interface1
和 Interface2
其中 Interface2
扩展 Interface1
.
interface Interface1 {
default void method() {
System.out.println("1");
}
// Other methods
}
interface Interface2 extends Interface1 {
@Override
default void method() {
System.out.println("2");
}
// Other methods
}
假设我想创建一个实现 Interface2
的 class,但我希望 method()
成为 Interface1
中的版本。如果我写
class MyClass implements Interface1, Interface2 {
public void method() {
Interface1.super.method();
}
}
我得到编译错误:
bad type qualifier in default super call: redundant interface Interface1 is extended by Interface2
可以通过创建第三个接口来解决这个问题:
interface Interface3 extends Interface1 {
default void method() {
Interface1.super.method();
}
}
然后:
class MyClass implements Interface1, Interface2, Interface3 {
public void method() {
Interface3.super.method();
}
}
这编译得很好,如果我实例化一个新的 MyClass
并调用 method()
,输出是预期的 1
。
所以我的问题是,考虑到只能为链中最具体的接口编写 InterfaceName.super.method()
的限制非常容易,限制的原因是什么?一开始就不允许您写 Interface1.super.method()
可以避免什么问题?
JLS 在 15.12.3. “编译时步骤 3:选择的方法是否合适?”.
If the form is TypeName . super . [TypeArguments] Identifier, then:
- […]
- If TypeName denotes an interface, let
T
be the type declaration immediately enclosing the method invocation. A compile-time error occurs if there exists a method, distinct from the compile-time declaration, that overrides (§9.4.1) the compile-time declaration from a direct superclass or direct superinterface of T
.
JLS 继续解释为什么制定规则:
In the case that a superinterface overrides a method declared in a grandparent interface, this rule prevents the child interface from "skipping" the override by simply adding the grandparent to its list of direct superinterfaces. The appropriate way to access functionality of a grandparent is through the direct superinterface, and only if that interface chooses to expose the desired behavior.
所以它或多或少是专门为了阻止你做你想做的事情而存在的。
但 JLS 似乎也承认您的解决方法:
(Alternately, the developer is free to define his own additional superinterface that exposes the desired behavior with a super method invocation.)
假设有两个接口 Interface1
和 Interface2
其中 Interface2
扩展 Interface1
.
interface Interface1 {
default void method() {
System.out.println("1");
}
// Other methods
}
interface Interface2 extends Interface1 {
@Override
default void method() {
System.out.println("2");
}
// Other methods
}
假设我想创建一个实现 Interface2
的 class,但我希望 method()
成为 Interface1
中的版本。如果我写
class MyClass implements Interface1, Interface2 {
public void method() {
Interface1.super.method();
}
}
我得到编译错误:
bad type qualifier in default super call: redundant interface Interface1 is extended by Interface2
可以通过创建第三个接口来解决这个问题:
interface Interface3 extends Interface1 {
default void method() {
Interface1.super.method();
}
}
然后:
class MyClass implements Interface1, Interface2, Interface3 {
public void method() {
Interface3.super.method();
}
}
这编译得很好,如果我实例化一个新的 MyClass
并调用 method()
,输出是预期的 1
。
所以我的问题是,考虑到只能为链中最具体的接口编写 InterfaceName.super.method()
的限制非常容易,限制的原因是什么?一开始就不允许您写 Interface1.super.method()
可以避免什么问题?
JLS 在 15.12.3. “编译时步骤 3:选择的方法是否合适?”.
If the form is TypeName . super . [TypeArguments] Identifier, then:
- […]
- If TypeName denotes an interface, let
T
be the type declaration immediately enclosing the method invocation. A compile-time error occurs if there exists a method, distinct from the compile-time declaration, that overrides (§9.4.1) the compile-time declaration from a direct superclass or direct superinterface ofT
.
JLS 继续解释为什么制定规则:
In the case that a superinterface overrides a method declared in a grandparent interface, this rule prevents the child interface from "skipping" the override by simply adding the grandparent to its list of direct superinterfaces. The appropriate way to access functionality of a grandparent is through the direct superinterface, and only if that interface chooses to expose the desired behavior.
所以它或多或少是专门为了阻止你做你想做的事情而存在的。
但 JLS 似乎也承认您的解决方法:
(Alternately, the developer is free to define his own additional superinterface that exposes the desired behavior with a super method invocation.)