为什么接口允许使用“默认”访问修饰符?

3

在Java中,接口默认情况下具有公共方法和常量,因此对于我来说,没有访问限定符的接口有点矛盾,就像下面的情况一样,尽管接口中的方法默认情况下应该是公共的,但是接口在定义它的包之外的包中甚至不可见。

package com.anirudh.package1;
interface IAccessSpecifierInterfaceTest {
    /**
     *
     * @param input
     */
    void implementMe(String input);
}

package com.anirudh.package2;

public class TryingToImplementDefaultInterfaceFromOtherPackage implements IAccessSpecifierInterfaceTest {
}

TryingToImplementDefaultInterfaceFromOtherPackage会出现错误(无法解析IAccessSpecifierTest)

有人知道何时需要使用默认访问权限的接口吗?为什么呢?

3个回答

3

当接口是包的实现的一部分而不是公共API的一部分时,可以将其设置为包保护。

尽管方法字段是隐式公共的,但防止访问整个接口仍然很有价值。

例如,假设您有一个解析和执行自定义脚本语言的包。解析是包内部的。抽象语法树中的所有节点都实现了一个公共接口。但该接口不是包的公共API的一部分。它可以被设置为包保护,以防止在包外部使用它。


不解释为什么接口中的方法只能在包内访问,但仍需要是公共的。基本上,为什么不允许包私有接口中的包私有方法?我相信编译器很容易实现这个功能?我相信 OP 知道默认访问权限是什么,所以才会提出这个问题。 - Chetan Kinger
那个相关的问题在https://dev59.com/y2435IYBdhLWcg3whASx中(糟糕地)得到了解答。我怀疑在Java早期设计阶段,公共访问被认为是最常见的用例。尽管如此,我已经看到过一些情况,我想指定`protected`访问以防止公共类实现时外部访问。 - Andy Thomas
即使公共访问是最常见的用例,为什么要将其强制作为方法的唯一用例呢?如果编译器可以在为没有构造函数的类创建默认构造函数时推断访问修饰符,那么对于接口方法也这样做会有多糟糕呢? - Chetan Kinger
@bot - 对于这个问题,接口可以具有默认访问权限的原因是有充分的理由的。至于您相关的问题,我不确定我们是否有一个好的答案。在https://dev59.com/gGox5IYBdhLWcg3wq2IC 上有一些猜测。特别是第一个答案及其初始评论。 - Andy Thomas

2

与保持其他内容“包保护”一样,有任何其他原因。

例如,假设您有一个调用另一个方法的方法,并使用参数指定在几种情况下应执行什么操作(最基本的示例:onSuccessonError)。 您很可能会使用接口在Java中实现此操作。

但是,这是为您自己的个人和内部使用而完成的。 您不希望向外部公开此接口。 使用您的软件包的任何人都没有(或不应该有)访问有问题的方法,因此他们没有真正的理由可以访问此接口。

以下是一个简短的代码示例,说明了该场景:

class DoingSomething {

    void doSomething(IResponse response) {
         if (/*do something*/) {
             response.onSuccess();
         } else {
             response.onError();
         }
    }

}

class AskForSomething {

      void ask() {
           new DoingSomething().doSomething(new IResponse() {

                void onSuccess() {
                     System.out.println("Success.");
                }

                void onError() {
                     System.err.println("error..");
                }
           });
      }
}

interface IResponse {
     void onSuccess();
     void onError();
}

在这种情况下,DoingSomethingAskForSomething是包保护的,因此IResponse也应该是包保护的,因为包外没有人能够访问接口或类/方法。

1
为什么不允许在包私有接口中使用包私有方法?我相信编译器很容易实现这个功能。我相信提问者知道默认访问权限是什么,那么这个问题是什么? - Chetan Kinger
@bot 使方法 "package scoped" 的目的是什么?这超出了接口的起源。 - Ernusc
@Ernusc:“这已经超出了接口的起源”。能解释一下吗? - Chetan Kinger

0

具有包范围的接口确实有其优点,但首先您必须想象,在哪种情况下使用包范围才有意义。我能想到的唯一一件事是特定于包的实现,可能不应在包外部使用。如果您可以接受这种推理,那么您肯定会得出结论,即所有设计模式都适用于这种情况,因此具有包范围的接口是有意义的。

现在唯一剩下的问题是,接口是用来做什么的?简而言之,它们定义了合同,即从实现该接口的类中可以期望什么。由于合同是公开的,即您希望方法及其签名可用,因此默认值只能为public。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接