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