我知道java中的包级保护是如何工作的.我读了很多代码(包括许多开源代码),似乎没有人使用它.整个保护级别对我来说似乎有点不对(我在一周的任何一天都有c#内部).
是否存在常用的合法的现实用例?
编辑:在问这个问题后有点太晚了,我意识到我忘了排除包受保护的实现类的"标准"模式,可能提供公共接口的实现.每个人都使用这些,正如回复中多次提到的那样.我仍然认为这个问题有很多很好的回复.
包级别可见性有两个很好的用途(根据我的经验):
1)在公共API中定义"内部"类.通常,您将接口和核心工厂定义为公共,将"内部"实现定义为包级别.然后,公共工厂可以构造包级实现类,并将它们作为公共接口的实例返回.这很好地允许用户只访问他们应该的东西.
缺点是你必须在同一个包中拥有所有这些东西,对于任何合理大小的API几乎都不是一个好主意. Java 7中的JSR 294/modules/Project Jigsaw有望通过指定一个新的可见性修饰符(module
)来提供替代方案,该修饰符可以用于跨模块访问模块中的类,而不会使它们在模块外部可见.您可以在本文中找到一个如何工作的示例.
2)单元测试是另一个常见的用例.通常你会看到一个src树和一个测试树,否则它们将是私有的东西而不是包级别,这样在同一个(并行)包中的单元测试就能够访问其他隐藏的方法来检查或操纵状态.
您是在谈论Java中的包私有保护吗?这是对类成员默认有效的保护.如果你的课程以需要额外信息或方法可见的方式密切互动,那么它偶尔会很有用.
假设您有一个Sink类,并且有几个类可以写入.Sink有一个接受基本数据类型的公共方法,以及一个接受原始字节数组的包私有方法.你不希望公开这个方法,因为你认为它的用户太低了,但你想让你的其他类(在Sink的包中)写入该Sink使用它.因此,您使方法接受字节数组包私有,并且您的包的类(如ByteStreamSource)可以使用它.现在,您的保护看起来像这样:
User Code using the package User ------ | -----------------------------|----- package public Interface | | Sink <- package priv. iface -> Sources
包私有接口与公共方法建立的公共接口正交.包私密性增加了封装,因为它鼓励你不公开不应公开的内容.它类似于friend
C++中的internal
关键字和C#中的关键字.
It can be used for implementation classes, for one thing. For example, EnumSet
is an abstract class, and no implementing classes are shown in the docs. Why? Because there are two implementing classes--one for enums with 64 or fewer elements, and one for 65 or more--and you don't really need to know which one you're using. In fact, you don't even need to know that there's more than one implementation. In fact, you don't even need to know that EnumSet
is abstract--you just need to know that you can call one of the static methods and get a Set
back.
在这种情况下,私有内部类可能已经足够(虽然不实用,特别是对于大型类).但有时包中的其他类需要访问此类实现细节.protected
可以工作,但随后他们也会对子类开放.
简而言之,它涵盖了其他三个保护级别无法处理的封装区域.
我认为原则上包级保护很有意义.它允许您创建靠近模块(包)的东西,但只暴露核心类.
例如,我的许多项目都使用公共接口和实现它们的"隐藏"类.用户使用工厂,并接收对应于"隐藏"具体实现的接口的引用.有了封装保护,理论上我应该只能暴露接口和工厂.
不幸的是,因为包保护不适用于子包,所以它并不适合我的工作方式.我喜欢使用其他包,特别是我的"内部"东西的子包(与Eclipse的组织方式相同).因此,我的包无法访问子包中的包级保护的东西.我希望有一天能改变这种状况.