Protected in Interfaces
为什么
因为一个接口的意思应该是"你能从类外看到什么"。添加非公共方法是没有意义的。
虽然经常被引用的原因是"接口定义公共API",但我认为这是一种过度简化。(它也"闻"到了循环逻辑。)
嵌套接口可以是受保护的,也可以是私有的,如果是这样的话,它根本就不定义公共接口。
拥有混合了访问修饰符的接口是没有意义的;例如,部分公共的接口,部分限制在与接口相同的包中的其他类。事实上,在某些情况下,这可能是非常有用的,IMO。
实际上,我认为将接口成员公开化的推理部分是使Java更简单:
隐式公共接口成员对于程序员来说更容易处理。你见过多少次代码(类)中的方法访问修饰符似乎是随机选择的?许多"普通"程序员很难理解如何最好地管理Java抽象边界。向接口添加public/protected/package使其更难实现。
隐式公共接口成员简化了语言规范…因此,Java编译器编写者的任务以及实现反射API的人们。
这种思路使得"接口定义公共API"成为语言设计的结果(或特征)。不是反过来。实际上,这两条思路可能是在Java设计者的头脑中并行开发的。
1-当然,顶尖的编程人员在这些方面没有困难,他们可能会欢迎更丰富的访问控制功能。但是,当他们的代码移交给其他人维护时会发生什么?
我不得不说,这个问题已经通过在Java 8中引入默认方法而重新打开。我现在正在研究的项目类似于接口的基本性质,它的目的是从实现中抽象出意图。
在某些情况下,我可以使用"默认保护"方法彻底简化代码。事实证明,这并不实际,因为接口仍然坚持Java 7逻辑。出于上述原因,一般的保护方法没有任何意义;但是,如果默认的公共方法需要一个不太可能更改的低级资源,并且可以由受保护的方法提供,在我看来,具有"默认保护"的工作不仅可以维护更干净的代码,还可以保护将来的用户。m意外滥用。
(可悲的是,这并没有改变这样一个事实:我仍然需要用不必要的抽象来过度复杂化我的代码;但我确实打算在Oracle中加入一个特性请求。)
因为接口定义了公共API。任何受保护的内容都是不属于接口的内部细节。
可以将抽象类与受保护的抽象方法一起使用,但接口仅限于公共方法和公共静态最终字段。
也许,因为它是一个接口,也就是说,它是用来告诉客户机他们可以用实例做什么,而不是告诉他们他们不能做什么。
接口是用来作为外部世界的"合同"。如果您想使用受保护的方法,最好使用抽象类(当然,如果Java中可用的话)。维基
另外,这篇文章可能还有一些很好的答案:为什么我不能保护接口成员?
我强烈认为接口应该允许受保护的方法;谁说接口必须对全世界的每个人都可见?至于你的观点,它可能会混淆"普通"(读:不称职)的程序员:很多OOP都是关于正确地构造对象、类、包等的,如果一个程序员很难正确地完成所有这些工作,他就有一个更大的问题。Java是为那种类型而构建的。
由于实现类必须实现接口中声明的所有方法,如果实现类位于不同的包中,会发生什么情况?
只有在子类扩展基类时,子类才能访问受保护的方法。
对于接口,子类从不扩展接口。它实现了接口。
受保护的方法可以通过扩展来访问,而不是通过实现来访问。
接口如果您想使用类似于您描述的东西,可以继续使用抽象类或嵌套接口。
代码样式中关于接口变量的练习,但仍适用于方法:
Interface variables are implicitly public because interfaces are intended to provide an Application Programming Interface (API) that is fully accessible to Java programmers to reference and implement in their own applications. Since an interface may be used in Java packages that are different from their own, public visibility ensures that program code can access the variable.
声明内部子接口是一个很好的实践,但是在技术上,你不能在Java接口中声明你的内部方法为EDCOX1 0。
当然,您可以为内部使用创建另一个扩展公共接口的接口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public interface YourPublicInterface { public void doThing1(); public void doThing2(); public void doThing3(); interface Internal extends YourPublicInterface { void doAnyInternalThing1(); void doAnyInternalThing2(); } } |
您可以在包中使用
1 2 3 4 5 6 7 8 9 10 11 | public class AClassInYourPackage { public void someMethod(YourPublicInterface param) { if (param instanceof YourPublicInterface.Internal) { // run the optimized code } else { // run the general code } } } |
在包外用户可以使用
在一般实践中,程序员在类似的情况下创建抽象类。但是,在这种情况下,我们会失去多重继承的好处。
唯一有意义的场景是,当您想要限制同一个包的可见性时。
甚至包场景也不是真正的接口。
为了实现您可能想要的,您需要两个接口,一个用于内部,另一个用于在公共API中公开。(内部的一个可能,但不一定扩展公共的一个)或者,正如其他人指出的,一个抽象的超类。
很好的问题是,如果被问到,为什么开发人员将接口属性公开而不受保护?
允许受保护将违反接口的策略/属性,"无论您提供什么抽象,都应该可以在任何地方无条件地访问,但不应该允许更改它。(例如:实例变量的值)
为了服务于这种用例,您应该避免使用接口。
接口成员总是在其自身外部(在类或结构中)进行修改/实现,因此它们是隐式公共的,不允许对其进行访问修饰符。甚至接口的成员也是公开实现的。但是,如果希望在提供实现的类中使成员私有,则需要显式实现接口。
1 2 3 4 5 6 7 8 9 | interface IMyIF { int MyMeth(int x); } //then it is legal to implement IMyIF as shown here: class MyClass : IMyIF { int IMyIF.MyMeth(int x) { return x / 3; } } |
显式实现为您提供了一种实现接口方法的方法,以便它不是提供实现的类的公共成员。