Java 8 引入了默认方法的概念。考虑以下带有默认方法的接口(interface):
public interface IDefaultMethod {
public abstract void musImplementThisMethod();
public default void mayOrMayNotImplementThisMethod() {
System.out.println(" This method is optional for classes that implement this interface ");
}
}
还有一个实现这个接口(interface)的类:
public class DefaultMethodImpl implements IDefaultMethod {
@Override
public void musImplementThisMethod() {
System.out.println("This method must be implementd ");
}
@Override
public void mayOrMayNotImplementThisMethod() {
// TODO Auto-generated method stub
IDefaultMethod.super.mayOrMayNotImplementThisMethod();
}
}
我对 mayOrMayNotImplementThisMethod
中以下调用的可读性有疑问:
IDefaultMethod.super.mayOrMayNotImplementThisMethod();
我理解在上面的调用中显式指定接口(interface)名称的原因是为了避免在类实现的多个接口(interface)具有相同方法的情况下混淆。我不明白的是 super
关键字在这种情况下的含义。当我们说 IDefaultMethod.super
时,我们在这里指的到底是什么? IDefaultMethod.mayOrMayNotImplementThisMethod() 不会比 IDefaultMethod.super.mayOrMayNotImplementThisMethod() 更具可读性吗?删除 super 关键字使其更具可读性,但以区分静态或非静态方法调用为代价。
最佳答案
我将尝试通过遵循我自己的推理来为讨论做出贡献。
使用类
首先,让我们看看它是如何与简单的 Java 类一起工作的:
class Barney {
void foo() { System.out.println("Barney says foo"); }
}
class Fred extends Barney {
@Override void foo() { super.foo(); }
}
在这种情况下,如果我们在 Fred
实例中调用方法 foo
,它将要求实现 foo
方法 在它的父类(super class)中并执行那个。
显然,这些其他方法都行不通:
@Override void foo() { foo(); } //means this.foo() so infinite recursion
@Override void foo() { Barney.foo(); } //means a static method
我们可以做第三种配置:
class Barney {
void foo() { System.out.println("Barney says foo"); }
class Fred extends Barney {
@Override void foo() { Barney.this.foo(); }
}
}
在这种情况下,如果我们在 Fred
的实例中调用 foo
,因为这个实例将与其封闭的实例有一个键,这个调用将调用
方法。Barney
的封闭实例中的 foo
例如
new Barney().new Fred().foo();
因此,此处使用 Barney.this
用于在内部/外部关系中的实例之间导航。
使用接口(interface)
现在让我们尝试在界面上重复同样的想法。
interface Barney {
default void foo() { System.out.println("Barney says foo"); }
}
interface Fred extends Barney {
@Override default void foo() { Barney.super.foo(); }
}
据我所知,这与类完全相同,只是在这种情况下,因为一个接口(interface)可以从多个接口(interface)继承,我们只需限定 super
关键字在这种情况下,使用我们定位的接口(interface)的名称。
意思是一样的,我们要在显式命名的超接口(interface)中调用foo
方法的“实现”。
与类一样,以下内容不起作用:
@Override default void foo() { super.foo(); } //can't be sure of which interface
@Override default void foo() { this.foo(); } //infinite recursion
@Override default void foo() { Barney.foo(); } //static method
@Override default void foo() { Barney.this.foo(); } //not an inner class relation
因此,这里合乎逻辑的选择是 Interface.super.method()
。
这里的一个问题是,在使用接口(interface)时,我们是否曾经有过像 Interface.this.method
这样的用例。
不是真的,因为接口(interface)代表一个静态的上下文,所以接口(interface)之间从来没有像内部类这样的概念。所以这是不可能的。
interface Barney {
default void foo() { System.out.println("Barney says foo"); }
interface Fred extends Barney {
@Override default void foo() { Barney.this.foo(); }
}
}
基本上,这是不可能的,因为上面的代码并不意味着 Fred
的实例需要存在于 Barney
的实例的上下文中。这只是一个静态内部接口(interface),它的实例可以独立于父接口(interface)的任何实例而存在。
所以,这就是为什么这不是一个好的选择。
因此,如您所见,毕竟使用 super
有点有意义,或者至少我希望我已经很好地解释了自己以传达这个想法。
关于Java 8 默认方法的可读性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28137440/