Java 8种默认方法可读性

Java 8 default method readability

Java 8介绍了默认方法的概念。考虑以下带有默认方法的接口:

public interface IDefaultMethod {

    public abstract void musImplementThisMethod();
    public default void mayOrMayNotImplementThisMethod() {
        System.out.println(" This method is optional for classes that implement this interface ");
    }

}

还有一个实现这个接口的 class :

    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();

我理解在上述调用中显式指定接口名称的原因是为了避免在 class 实现的多个接口具有相同方法的情况下混淆。我不明白的是 super 关键字在这种情况下的含义。当我们说 IDefaultMethod.super 时,我们指的到底是什么? IDefaultMethod.mayOrMayNotImplementThisMethod() 不会比 IDefaultMethod.super.mayOrMayNotImplementThisMethod() 更具可读性吗?删除 super 关键字使其更具可读性,但以区分静态或非静态方法调用为代价。

这只是对访问 superclasses (JLS 15.11):

成员的常用方法的默认方法的扩展

The form T.super.Identifier refers to the field named Identifier of the lexically enclosing instance corresponding to T, but with that instance viewed as an instance of the superclass of T.

本质上,当 class 有多个祖先时(无论是因为默认方法还是仅仅因为它有多个 superclasses 在层次结构)。 super 关键字是内部 class 中 Outer.this 的类比;这意味着你想得到“this,但我会在那个超级class的主体内看到的东西,而不是这个子class内的成员”。

super 指的是 class 或您继承的接口。这意味着您想调用一个方法而忽略它已被覆盖的事实。

如果您使用 this,您将引用此 class(或子 class),因此具有无限递归。

我会根据自己的推理来为讨论做出贡献。

使用类

首先,让我们看看它如何使用简单的 Java classes:

class Barney {
    void foo() { System.out.println("Barney says foo"); }
}

class Fred extends Barney {
    @Override void foo() { super.foo(); }
}

在这种情况下,如果我们在 Fred 实例中调用方法 foo,它将要求 实现 foo 方法 在它的 super class 中执行那个。

显然,none 这些其他人可以工作:

@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,因为此实例与其封闭实例有一个键,此调用将调用 foo 中的方法Barney.

的封闭实例

例如

new Barney().new Fred().foo();

因此,此处使用 Barney.this 用于在 inner/outer 关系中的实例之间导航。

使用界面

现在让我们尝试对接口重复相同的想法。

interface Barney {
    default void foo() { System.out.println("Barney says foo"); }
}


interface Fred extends Barney {
    @Override default void foo() { Barney.super.foo(); }
}

据我所知,这与 classes 完全相同,只是在这种情况下,因为一个接口可以继承自多个接口,我们只需限定 super 关键字与我们在这种情况下定位的接口的名称。

意思是一样的,我们要在显式命名的super接口中调用foo方法的"implementation"

与 classes 一样,以下内容不起作用:

@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.this.method 这样的用例。

不完全是,因为接口代表静态上下文,因此接口之间从来没有像内部 classes 那样的概念。所以这是不可能的。

interface Barney {
    default void foo() { System.out.println("Barney says foo"); }

    interface Fred extends Barney {
            @Override default void foo() { Barney.this.foo(); }
    }
}

基本上,这是不可能的,因为上面的代码并不意味着 Fred 的实例需要存在于 Barney 的实例的上下文中。这只是一个静态内部接口,它的实例可以独立于父接口的任何实例而存在。

所以,这就是为什么这不是一个好的选择。

因此,如您所见,毕竟 super 的使用是有道理的,或者至少我希望我已经很好地解释了自己以传达这个想法。

Java8个接口也有静态方法

如果你说, IDefaultMethod.mayOrMayNotImplementThisMethod();
那么就是调用静态方法的方式,貌似也是正确的,和我们访问class的静态成员类似。

对于默认方法,如果未使用 'super' 那么他们可能会使用 'this',这没有意义,因为 'this' 属于我们所在的 class进行方法调用。

我的意见是,你是对的,因为它没有提供良好的可读性,但似乎符合语言设计。