我一直在寻找,我知道理论上的差异。
这一切都很好,问题是,它们之间的实用区别是什么?您何时会使用private
,何时使用protected
?这个是否有标准或可接受的良好做法?
到目前为止,为了保留继承和多态的概念,我将public
用于任何应该从外部访问的内容(如构造函数和主类功能),并使用protected
作为内部方法(逻辑,辅助方法等)。我是在正确的轨道上吗?
(请注意,这个问题适合我,但也可供将来参考,因为我没有看到像这样的问题)。
答案 0 :(得分:122)
不,你没有走上正轨。一个好的经验法则是:尽可能将所有内容都设为私有。这使您的类更加封装,并允许更改类的内部,而不会影响使用您的类的代码。
如果你设计你的类是可继承的,那么仔细选择可以从子类覆盖和访问的内容,并使其受到保护(最后,如果你想让它可访问但不能覆盖,那么谈论Java)。但请注意,只要您接受具有类的子类,并且存在受保护的字段或方法,此字段或方法就是该类的公共API的一部分,并且在不破坏子类的情况下可能不会在以后更改。
不应该继承的类应该是最终的(在Java中)。为了进行单元测试,您可以放松一些访问规则(私有到受保护,最终到非最终),然后记录它,并明确表示尽管该方法受到保护,但它不应该被覆盖。
答案 1 :(得分:42)
让我先说一下我在这里主要谈论方法访问,并在较小程度上标记类最终,不成员访问。
古老的智慧
在开源管理开发人员库空间和VCS /依赖关系mgmt之前,“将其标记为私人,除非您有充分理由不”
在写入的日子里有意义。由于Github,Maven等原因,它变成了超级协作。当时,通过限制图书馆的使用方式也可以赚钱。我职业生涯的前8或9年大概坚持这种“最佳实践”。
今天,我认为这是一个糟糕的建议。有时候有一个合理的论据来标记一个方法私有,或一个类最终,但它是非常罕见的,即使这样,它可能没有改进任何东西。
你有没有:
这是我在默认情况下将方法标记为私有的三个最大的合理化:
我无法计算我是否有必要覆盖我所写的特定方法的错误次数。我曾经在几个流行的开源库中工作,我很难学会将事物标记为私有的真正成本。它通常会消除解决问题或用例的唯一实用解决方案。相反,我已经从未在16年以上的专业发展中,因为与API安全相关的原因而对保护而非私有的方法表示遗憾。当开发人员选择扩展一个类并覆盖一个方法时,他们会有意识地说“我知道我在做什么”。为了生产力,应该足够了。期。如果它是危险的,请注意它在类/方法Javadocs中,不要盲目地关上门。
默认保护的标记方法可以缓解现代软件开发中的一个主要问题:想象力的失败。
这个更合理,并且取决于目标受众甚至可能是正确的事情,但是值得考虑保持API“干净”的成本实际上是:可扩展性。由于上面提到的原因,为了以防万一,标记受保护的内容可能更有意义。
这也是合理的,但作为消费者,我每次都会选择限制较少的竞争对手(假设不存在明显的质量差异)。
我不是说永远不会将方法标记为私有。我说更好的经验法则是“除非有充分的理由不让方法受到保护”。
此建议最适合那些已经分解为模块的图书馆或大型项目的人员。对于较小或较多的单片项目,由于您无论如何都要控制所有代码,因此不太重要,如果需要,可以轻松更改代码的访问级别。尽管如此,我仍然会给出同样的建议: - )
答案 2 :(得分:16)
我刚才读了一篇文章,谈到尽可能地锁定每个班级。除非您有 立即 需要向外界公开某些数据或功能,否则请将所有内容设为最终版和私密版。在以后扩展范围总是很容易,但不是相反。首先考虑制作尽可能多的内容final
,这样可以更轻松地在private
和protected
之间进行选择。
现在,如果你留下最后一堂课,那么除非世界绝对需要一些东西,否则要把所有东西都当作私人 - 让它公之于众。
如果你留下了一个确实有子类的类,那么仔细检查每个属性和方法。首先考虑是否要将该属性/方法公开给子类。如果你这样做,那么考虑一个子类是否会对你的对象造成严重破坏,如果它在覆盖过程中弄乱了属性值或方法实现。如果可能的话,你想要保护你的类的属性/方法,即使是从子类(听起来很讽刺,我知道),然后把它变成私有的。否则让它受到保护。
免责声明:我在Java中编程不多:)
答案 3 :(得分:14)
停止滥用私人领域!!!
这里的评论似乎非常支持使用私人领域。那么,我有不同的想法。
原则上私人领域是否良好?是。但是当你不确定 肯定是错误的时,说黄金法则会使一切变得私密!在遇到问题之前,你不会看到问题。在我看来,如果您不确定,则应将字段标记为受保护。
您希望扩展一个类有两种情况:
第一种情况下私人领域没有任何问题。人们滥用私人字段这一事实会让你感到非常沮丧,因为你发现你无法修改狗屎。
考虑一个模拟汽车的简单库:
class Car {
private screw;
public assembleCar() {
screw.install();
};
private putScrewsTogether() {
...
};
}
图书馆作者认为:我的图书馆用户没有理由需要访问assembleCar()
的实施细节吗?让我们把螺丝标记为私有。
嗯,作者错了。如果你只想修改assembleCar()
方法而不将整个类复制到你的包中,那你就不走运了。您必须重写自己的screw
字段。让我们说这辆车使用了十几个螺丝,每个螺丝都涉及一些不同的私人方法中的一些重要的初始化代码,这些螺丝都标记为私有。在这一点上,它开始吮吸。
是的,您可以和我争辩说,图书馆作者可以编写更好的代码,因此私有字段没有任何问题。我并不认为私有字段是 OOP 的问题。当人们使用它时,这是一个问题。
故事的寓意是,如果你正在写一个图书馆,你永远不知道你的用户是否想要访问一个特定的领域。如果您不确定,请将其标记为protected
,以便以后每个人都会更开心。 至少不要滥用私人领域。
我非常支持尼克的回答。
答案 4 :(得分:6)
您何时会使用private
以及何时使用protected
?
隐私继承视为 根据 关系实施,而不是 IS-A 关系。简单地说,继承类的外部接口与继承类没有(可见)关系,它仅使用private
继承来实现Base类提供的类似功能。
与Private Inheritance不同,受保护的继承是一种受限制的继承形式,其中派生类 IS-A 类型的Base类并且它希望将派生成员的访问权限仅限于派生类。
答案 5 :(得分:2)
如果付款类处理付款结算然后在产品类中为什么它需要整个计费过程,即支付方法如何支付在哪里支付,那么这就是封装的全部内容..所以只能让用于其他的东西对于那些其他类也会使用的类而言,类和对象只不过是那些公共类,对于那些仅限于扩展类的限制而言受到保护。因为你是madara uchiha私人就像"limboo"
你可以看到它(你只上课一个班级)。