Private vs Protected - Visibility Good-Practice Concern
我一直在寻找,我知道理论上的不同。
- 公共-任何类/函数都可以访问方法/属性。
- 受保护-只有此类和任何子类可以访问方法/属性。
- private-只有此类可以访问方法/属性。它甚至不会被继承。
很好,问题是,它们之间的实际区别是什么?你什么时候使用
到目前为止,为了保留继承和多态性的概念,我使用
(请注意,这个问题是为我准备的,但也供以后参考,因为我没有见过这样的问题)。
不,你走错了。一个很好的经验法则是:尽可能地让一切都变得私人化。这使得类更加封装,并允许在不影响使用类的代码的情况下更改类的内部。
如果将类设计为可继承的,那么仔细选择可能被子类重写和可访问的内容,并使其受到保护(并且,如果您想使其成为可访问的但不可重写的话,则要讲Java)。但是请注意,一旦您接受了类的子类,并且有一个受保护的字段或方法,那么这个字段或方法就是类的公共API的一部分,以后在不破坏子类的情况下不能更改。
不打算继承的类应该是最终的(在Java中)。为了进行单元测试,您可以放宽一些访问规则(私有到受保护,最终到非最终),但随后对其进行文档记录,并明确表示尽管该方法受保护,但不应该重写它。
首先,我要说的是,我在这里主要讨论方法访问,在稍微小一点的范围内,将类标记为最终的,而不是成员访问。
旧智慧
"mark it private unless you have a good reason not to"
在开发人员库空间和VCS/Dependency Management还未被开源所统治之前,这在编写它的日子里是有意义的。由于Github、Maven等原因,它变得高度协作。那时,通过限制图书馆的使用方式,也可以赚钱。我在职业生涯的头8到9年里,可能都严格遵守了这个"最佳实践"。
今天,我认为这是个坏建议。有时有合理的理由将方法标记为private,或类final,但这是非常罕见的,即使这样,它也可能不会改进任何东西。
你曾经有过:
- 对一个库等感到失望、惊讶或伤害,因为它有一个可以通过继承和很少几行代码修复的bug,但是由于私有/最终方法和类被迫等待一个可能永远不会出现的官方补丁?我有。
- 想要将库用于与作者设想的稍有不同的用例,但由于私有/最终方法和类而无法这样做?我有。
- 对一个在可扩展性方面过于宽松的库等感到失望、惊讶或伤害?我没有。
这是我听到的三个最大的合理化,默认情况下将方法标记为私有:
合理化1:这是不安全的,没有理由重写特定的方法对于是否需要重写我编写的特定方法,我无法计算出我出错的次数。在研究了几个流行的开源libs之后,我学到了将事物标记为私有的真正代价。它经常消除不可预见的问题或用例的唯一实际解决方案。相反,在16年多的专业发展中,我从来没有因为与API安全相关的原因而后悔将方法标记为受保护而不是私有。当开发人员选择扩展一个类并重写一个方法时,他们会有意识地说"我知道我在做什么",并且为了提高工作效率,这应该足够了。时期。如果这很危险,请在类/方法javadocs中注意,不要盲目地关上门。
默认保护的标记方法是对现代软件开发中的一个主要问题的缓解:想象的失败。
合理化2:保持公共API/JavaDocs的清洁这一点更为合理,根据目标受众的不同,它甚至可能是正确的做法,但值得考虑的是保持API"干净"的实际成本是:可扩展性。出于上述原因,为了以防万一,标记默认保护的对象可能更有意义。
合理化3:我的软件是商业化的,我需要限制它的使用。这也是合理的,但作为一个消费者,我每次都会选择限制性较小的竞争对手(假设没有明显的质量差异)。
永不言败我不是说永远不要将方法标记为私有。我是说更好的经验法则是"让方法受到保护,除非有充分的理由不这样做"。
这个建议最适合那些在图书馆或更大规模的项目上工作的人,这些项目已经被分解成模块。对于更小或更大的单块项目来说,这并没有那么重要,因为不管怎样,您都可以控制所有代码,并且在需要时可以很容易地更改代码的访问级别。尽管如此,我还是会给出同样的建议:—)
我刚才读了一篇文章,说要尽可能地把每门课都锁起来。使所有内容最终化和私有化,除非您立即需要向外部世界公开某些数据或功能。扩展范围是很容易的,以便在以后更为允许,但不是反过来。首先考虑做尽可能多的东西来选择
现在,如果你只剩下最后一节课,那就把所有的事情都变成私人的,除非世界上绝对需要的东西——把它公之于众。
如果您只剩下一个具有子类的类,那么请仔细检查每个属性和方法。首先考虑是否要将该属性/方法公开到子类。如果这样做,那么考虑如果子类在重写过程中破坏了属性值或方法实现,它是否会对对象造成破坏。如果可能的话,并且您想要保护类的属性/方法,甚至不受子类的影响(听起来很讽刺,我知道),那么就将其设为私有的。否则要保护它。
免责声明:我在爪哇的计划不多:
停止滥用私人领域!!!!
这里的评论似乎压倒性地支持使用私有领域。好吧,那我有别的话要说。
私人领域原则上是好的吗?对。但是说一个黄金法则就是在你不确定的时候把所有的事情都保密,这绝对是错误的!在遇到问题之前,你是看不到问题的。在我看来,如果您不确定,您应该将字段标记为受保护。
有两种情况需要扩展类:
- 您想向基类添加额外的功能
- 要修改当前包之外的现有类(可能在某些库中)
在第一种情况下,私有字段没有问题。人们滥用私人领域的事实让你发现自己无法修改狗屎时很沮丧。
考虑一个简单的汽车模型库:
1 2 3 4 5 6 7 8 9 | class Car { private screw; public assembleCar() { screw.install(); }; private putScrewsTogether() { ... }; } |
图书馆作者认为:我的图书馆用户没有理由访问
嗯,作者错了。如果您只想修改
是的,你可以和我争论,图书馆作者本可以写更好的代码,这样私有字段就没有问题了。我不是说私人领域是OOP的问题。当人们使用它们时是一个问题。
这个故事的寓意是,如果你在写一个图书馆,你永远不知道你的用户是否想访问某个特定的领域。如果你不确定的话,把它标记为1(3),这样每个人以后都会更快乐。至少不要滥用私人领域。
我非常支持尼克的回答。
你什么时候使用
私有继承可以从关系的角度来考虑,而不是从IS-A关系的角度来考虑。简单地说,继承类的外部接口与继承类没有(可见)关系,它只使用
与私有继承不同,受保护继承是一种受限制的继承形式,其中派生类是一种基类,它希望将派生成员的访问仅限于派生类。
好吧,这都是关于封装的,如果PayBill类处理付款的账单,那么在产品类中,为什么它需要整个账单流程,即付款方式,如何支付到哪里付款。因此,对于那些其他类也会使用的类和对象,只允许将用于其他类和对象的内容放在公共内容之外,仅对扩展类的限制进行保护。因为你是内海夫人,私人学校就像是江户一号(6号),你可以看到它(你只上一个班)。