【问题标题】:Why is the "Default" access specifier allowed for interfaces?为什么接口允许使用“默认”访问说明符?
【发布时间】:2015-04-19 15:20:42
【问题描述】:

由于 Java 中的接口具有默认公共的方法和常量,因此对我来说,具有默认(或无)访问说明符的接口有些矛盾,如下例所示,尽管接口中的方法应该是默认情况下是公共的,但该接口甚至在它定义的包之外的包中都不可见。

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

package com.anirudh.package2;

public class TryingToImplementDefaultInterfaceFromOtherPackage implements IAccessSpecifierInterfaceTest {
}

TryingToImplementDefaultInterfaceFromOtherPackage 给出错误(无法解析 IAccessSpecifierTest

有没有人知道任何实际场景可以保证接口具有默认访问权限?为什么?

【问题讨论】:

    标签: java interface


    【解决方案1】:

    只要接口是包实现的一部分,而不是其公共 API 的一部分,它就可以受到包保护。

    虽然methodsfields 是隐式公开的,但阻止对整个接口的访问仍然很有价值。

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

    【讨论】:

    • 没有解释为什么只能在包中访问的接口中的方法仍然需要公开。基本上,为什么不允许包私有接口中的包私有方法?我确信这可以很容易地在编译器中实现?我相信 OP 知道默认访问是什么,因此问题是什么?
    • stackoverflow.com/questions/5376970/protected-in-interfaces 中解决了这个相关问题(很差)。我怀疑在 Java 的早期设计过程中,公共访问被认为是最常见的用例。尽管如此,我还是看到了一些我想指定 protected 访问权限以防止在公共类实现时访问包外的情况。
    • 即使公共访问是最常见的用例,为什么要强制它作为方法的唯一用例?如果编译器可以在为没有构造函数的类创建默认构造函数时推断访问修饰符,那么对接口方法做同样的事情会有多糟糕?
    • @bot - 对于这个问题,接口可以具有默认访问权限是有充分理由的。对于您的相关问题,我不确定我们是否有一个好的答案。 stackoverflow.com/questions/9046012/… 有一些猜测。请特别查看第一个答案及其初始 cmets。
    【解决方案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 也应该是包保护的,因为包外的任何人都不能访问接口或类/方法。

    【讨论】:

    • 为什么不允许包私有接口中的包私有方法?我确信这可以很容易地在编译器中实现?我相信 OP 知道默认访问是什么,因此问题是什么?
    • @bot 使方法“包范围”的目的是什么?它超越了接口的起源
    • @Ernusc It's beyond of interfaces origin。解释一下?
    【解决方案3】:

    带有包作用域的接口确实有它们的好处,但首先你必须想象一下,在什么情况下使用包作用域是有意义的。我能想到的唯一一件事是可能会或不应该在包外使用的包特定实现。如果你能接受这种推理,你肯定会得出结论,即使在这种情况下,所有设计模式都适用,因此与包范围的接口确实有意义。

    现在唯一要问的是,接口是做什么用的?简而言之,他们定义了对实现该接口的类的期望的合同。由于合约是公开的,即您希望方法及其签名可用,默认只能是公开的。

    【讨论】:

      猜你喜欢
      • 2011-12-10
      • 2013-12-27
      • 2011-06-15
      • 2016-01-15
      • 2013-12-25
      • 2011-09-17
      • 2011-01-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多