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