Java 8 默认方法的可读性

标签 java default-method

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/

相关文章:

java - 有关所使用的 JUnit jar 版本的 Ant JUnit 任务报告(例如 Junit 3、3.8、4)

java - 特定模式作为模运算符的输出

debugging - Java调试器无法调用某些默认方法实现

java - 使用 ECJ 的 Lambda/默认方法/类型删除怪癖/错误?

java - 为什么 Delayed 不为 compareTo 提供默认方法?

java - 实现相同接口(interface)的 DTO 和实体

java - ScheduleAtFixedRate 执行速度快

java - 使用java定时器

java - 必须实现默认接口(interface)方法?

java - 类中的静态方法与接口(interface)中的默认方法具有相同的签名