我想知道为什么 Java 的设计没有friend
C++ 中可用的指令,以允许更好地控制哪些方法和实例变量可从定义类的包外部获得。
我没有看到任何实际原因或任何具体缺点,这似乎只是一个设计问题,但如果添加到语言中不会造成任何问题。
我想知道为什么 Java 的设计没有friend
C++ 中可用的指令,以允许更好地控制哪些方法和实例变量可从定义类的包外部获得。
我没有看到任何实际原因或任何具体缺点,这似乎只是一个设计问题,但如果添加到语言中不会造成任何问题。
总的来说,我认为这是因为它增加了认知复杂性,而且它创造了改进的案例数量很少。
我想说,此刻生产中的大量java行可以证明friend
关键字并不是真正的大损失:)。
有关更具体的原因,请参阅@dwb 的回答。
以下是我脑海中浮现的几个原因:
只有非常天真和缺乏经验的程序员才会反对朋友。当然,它可能会被滥用,但公共数据也可以,但提供了这种功能。
与流行观点相反,这里有很多情况,特别是对于基础设施功能,朋友访问导致更好的设计,而不是更差的设计。当一个方法被强制公开而实际上不应该公开时,通常会违反封装,但我们别无选择,因为 Java 不支持朋友。
除了前面提到的包可见性之外,Java 还提供了内部类和匿名类,它们不仅默认是朋友,而且自动具有对包含类的引用。由于创建此类帮助程序类可能是在 C++ 中使用的唯一合理方式friend
,Java 不需要它,因为它有另一种机制。迭代器就是一个很好的例子。
完全同意spaceghost在他的回答中的说法
与流行观点相反,这里有很多情况,特别是对于基础设施功能,朋友访问导致更好的设计,而不是更差的设计。
我的例子很简单——如果一个类 A 必须在 java 中为类 B 提供一个特殊的“朋友”接口,我们必须将它们放在同一个包中。没有例外。在这种情况下,如果 A 是 B 的朋友并且 B 是 C 的朋友,则 A 必须是 C 的朋友,这并不总是正确的。这种“友谊传递性”打破了封装,而不是 C++ 友谊可能导致的任何问题。
为什么不简单地认为 Java 需要将友元类放在一起呢?包私有可见性允许同一包中的每个人访问这些成员。因此,您不仅限于明确声明的朋友,而且您允许任何(现有或未来)朋友更改一些专门为此目的设计的成员(但不是您的私人内容)。您仍然可以完全依赖封装。
只是添加到其他答案:
Java 中有默认的包可见性。因此,您可以调用同一包邻居中的所有类。在这种情况下,您可以明确控制向邻居显示的内容 - 只是具有包可见性的成员。
所以,它不是真正的朋友,但可以是相似的。是的,这也会导致糟糕的设计......
在我看来,某种朋友特性(不一定与 C++ 非常相似)在 Java 的某些情况下会非常有用。目前我们有包私有/默认访问黑客,以允许在同一个包(例如)中紧密耦合的类之间进行协作String
,StringBuffer
但这会打开整个包的私有实现接口。在包之间,我们有邪恶的反射黑客,这会导致一大堆问题。
在 Java 中执行此操作有一点额外的复杂性。C++ 在解决函数重载(和类似问题)时忽略访问限制 - 如果程序编译#define private public
不应该做任何事情。Java(大部分)丢弃不可访问的成员。如果需要考虑友谊,则解决方案会更加复杂且不那么明显。