私人vs保护 – 可见性良好的实践关注

我一直在寻找,我知道理论上的差异。

  • public – 任何类/函数都可以访问方法/属性。
  • 保护 – 只有这个类和任何子类可以访问方法/属性。
  • 私人 – 只有这个类可以访问方法/属性。 它甚至不会被inheritance。

这一切都很好,问题是,他们之间的实际区别是什么? 什么时候你会使用private ,什么时候使用protected ? 有没有一个标准的或可接受的良好的做法,这一个?

到目前为止,为了保留inheritance和多态的概念,我使用public来从外部访问(比如构造函数和主类的function),并为内部方法(逻辑,辅助方法等)提供保护。 我在正确的轨道上?

(请注意,这个问题对我来说,也是为了将来的参考,因为我没有看到像这样的问题)。

不,你不在正确的轨道上。 一个好的经验法则是:尽可能使所有东西尽可能私人化。 这使得你的类更加封装,并且允许改变类的内部而不影响使用你的类的代码。

如果您将类devise为可inheritance的,那么请仔细select可能被子类覆盖并可访问的对象,并使其受保护(如果要使其可访问但不可覆盖,则最终讨论Java)。 但请注意,只要您接受具有您的类的子类,并且有一个受保护的字段或方法,则此字段或方法是该类的公共API的一部分,并且不会在不中断子类的情况下进行更改。

一个不打算被inheritance的类应该是最终的(用Java)。 为了进行unit testing,您可以放松一些访问规则(私有受保护,最终到非最终),然后将其logging下来,并明确指出虽然该方法是受保护的,但不应该被覆盖。

我前段时间看过一篇文章,谈到尽可能地locking每个class级。 除非你立即需要向外界公开一些数据或function,否则一切都是最终的和私人的。 将范围扩大到稍后允许的范围总是很容易的,而不是相反。 首先考虑尽可能多的事情做finalselect之间的privateprotected更容易。

  1. 使所有的类最终,除非你需要立即子类。
  2. 使所有的方法都是最终的,除非你需要子类并重写它们。
  3. 使所有的方法参数都是最终的,除非你需要在方法体内改变它们,这在大多数情况下都是有点笨拙的。

现在,如果你剩下的是最后一堂课,那么除非世界上绝对需要什么东西,否则就把所有东西都私下化,这样做是公开的。

如果你留下一个具有子类的类,那么仔细检查每个属性和方法。 首先考虑是否要将该属性/方法公开给子类。 如果你这样做,那么考虑一个子类是否会在重写的过程中混淆了属性值或方法实现,从而对你的对象造成严重破坏。 如果可能的话,你想保护你的class级的财产/方法,甚至从子类(听起来很讽刺,我知道),然后把它变成私人的。 否则使其保护。

免责声明:我不用Java编程太多:)

让我先说这个,我说的主要是关于这里的方法访问,稍微地说,最终标记类, 而不是成员访问。

旧的智慧

“除非你有充分的理由不要”

在开放源代码占据开发者库空间和VCS /依赖性pipe理之前的日子里是有意义的。 Github,Maven等成为了超级合作伙伴。当时还有钱可以通过限制图书馆的使用方式来实现。 我大概花了我职业生涯的第8或9年严格遵守这个“最佳做法”。

今天,我相信这是不好的build议。 有时候有一个合理的论点来标记一个私有的方法,或者一个类的最后一个,但是这个方法非常罕见,即使这样也没有什么改进。

你有没有:

  • 被图书馆等感到失望/惊讶/伤害,有一个可以通过inheritance和几行代码修复的bug,但由于私人/最终的方法和类,被迫等待官方补丁?
  • 想要使用一个稍微不同于作者想象的用例的图书馆,但由于私人/最终的方法和课程而无法这样做?
  • 被图书馆等感到失望/惊讶/伤害,这是在扩展性过分宽容吗?

这些是我听说默认标记私有方法的三种最合理的方法:

合理化#1:这是不安全的,没有可以想象的理由来覆盖特定的方法

我无法计算出我是否曾经需要重写一个我写的特定方法的错误次数。 在研究过几个stream行的开源库之后,我学会了将事物标记为私有的真正代价。 它通常消除了对未解决的问题或用例的唯一实际解决scheme。 相反,我从来没有参与过16年以上的职业发展,因为有关API安全的原因,我感到遗憾的是标记了一种保护方法,而不是私有方法。 当一个开发者select扩展一个类并重写一个方法时,他们有意识地说“我知道我在做什么”。 为了生产力就够了。 期。 如果是危险的,请在class级/方法Javadocs中记下,不要盲目地关上门。

标记方法的默认保护是缓解现代软件开发的一个主要问题:想象力的失败。

合理化#2:它保持公共API / Javadocs清洁

这实际上是非常合理的,并且根据目标受众甚至可能是正确的做法,但值得考虑的是保持API“干净”的成本实际上是:可扩展性。 由于上面提到的原因,为了以防万一,默认保护的东西可能还是有意义的。

合理化#3:我的软件是商业的,我需要限制它的使用。

这个其实很合理。 作为一个消费者,尽pipe我会每一次与限制较less的竞争对手(假设没有显着的质量差异存在)。

永不说永不

我不是说永远不要将方法标记为私有。 我断言,更好的经验法则是“除非有充分的理由不要保护方法”。

这个build议最适合那些从事图书馆或大型项目的人员,这些项目已经被分解成模块。 对于规模较小或者更多的整体项目,由于您无论如何都控制了所有的代码,所以它并不重要,在需要的时候很容易改变代码的访问级别。 即使如此,我仍然会给出相同的build议:-)

什么时候你会使用private ,什么时候使用protected

私人inheritance可以被认为是关系而不是一个IS-A关系来实现的。 简而言之,inheritance类的外部接口与inheritance的类没有(可见的)关系,它只使用privateinheritance来实现Base类提供的类似function。

与私有inheritance不同, 受保护的inheritanceinheritance的一种限制forms,其中派生类IS-A是基类的一种,并且它想要将派生成员的访问仅限于派生类。

停止滥用私人领域!

这里的评论似乎绝对支持使用私人领域。 那么,我有一些不同的说法。

私人领域原则上是好的吗? 是。 但是说一个金科玉律,就是把一切都隐藏起来,当你不确定的时候肯定 是错的 ! 遇到问题后才能看到问题。 在我看来, 如果你不确定的话你应该把领域标记为受保护的

有两种情况你想扩展一个类:

  • 您想要为基类添加额外的function
  • 你想修改当前包之外的现有类(也许在一些库中)

在第一种情况下,私人领域没有任何问题。 事实上,人们滥用私人领域使你感到沮丧,当你发现你不能修改狗屎。

考虑一个简单的汽车模型库:

 class Car { private screw; public assembleCar() { screw.install(); }; private putScrewsTogether() { ... }; } 

图书馆作者认为:我的库的用户没有理由需要访问assembleCar()的实现细节吗? 我们把螺丝标记为私人。

那么,作者是错的。 如果您只想修改assembleCar()方法而不将整个类复制到您的包中,那么您运气不好。 你必须重写你自己的screw领域。 比方说,这辆车使用了十几个螺丝,每个螺丝都包含了一些不同的私有方法的一些平凡的初始化代码,而且这些螺丝都是标记为私有的。 在这一点上,它开始吮吸。

是的,你可以和我争辩说, 图书馆作者可以写出更好的代码,所以私人领域没有任何问题 。 我不认为私人领域是OOP的问题。 当人们使用它们时,这是一个问题。

故事的寓意是,如果你正在编写一个图书馆,你永远不知道你的用户是否想要访问一个特定的领域。 如果您不确定,请将其标记为protected以便以后每个人都更快乐。 至less不要滥用私​​人领域

我非常支持Nick的回答。

那么这是关于封装如果付款类处理付款然后在产品类为什么它需要整个过程的结算过程,即支付方法如何支付支付..所以只有让什么是用于其他类和对象只不过是那些其他阶级也会使用的公众而已,只为扩大阶级而受到保护。 因为你是madara uchiha私人像"limboo"你可以看到它(你只上课单)。