你什么时候写私人方法,而不是保护?
如果我正在写一个类,那么我什么时候可以私有化一个方法,而不是保护? 换句话说,我怎么可以事先知道客户端程序员永远不需要重写一个方法? 在一些有外部考虑的情况下,如数据库连接?
public
方法和protected
方法构成了你的对象的“接口”,对于使用(委托给你的类)的开发人员是public
的,并且对于希望通过inheritance你的对象的function来扩展它的function的开发者来说是protected
的。
请注意,即使您的课程将被分类,也没有必要提供protected
方法。
public
接口和protected
接口都需要仔细考虑,特别是如果这是一个由您的控制之外的开发人员使用的API,因为对接口的更改可能会破坏对现有接口如何工作的假设的程序。
private
方法纯粹是对象的作者,可能会被重构,更改和删除。
我会默认使用private
的,如果你发现你需要公开更多的方法,仔细考虑如何使用它们 – 特别是如果它们是虚拟的 – 如果它们被另一个任意替代函数完全replace会发生什么开发人员,你的课程还会继续吗? 然后devise一些适当的protected
,对开发人员进行子类化(如果有必要)是有用的,而不是暴露现有的function。
换句话说,我怎么可以事先知道客户端程序员永远不需要重写一个方法?
你不能。 你不需要。 如果一个开发人员可能想要重写一个方法,那么预测这不是你的工作,更不用说如何了 。 假设他想要让他这样做,而不必触摸你的代码。 基于这个原因,如果你不需要的话,不要private
声明方法。
如果开发人员觉得他需要调整类的某些function,他可以从一些结构和行为模式中select,例如装饰器,适配器或者inheritance类。 使用这些模式是很好的,因为它将更改封装到开发人员自己的类中,并且保持自己的代码不变。 通过将方法声明为private
,您可以确保开发人员将猴子与您的class级。 那很糟糕。
一个完美的例子是Zend Framework的数据库适配器。 他们不鼓励使用持续连接,而且他们的适配器为此提供了不重要的意义。 但是,如果你想拥有这个,并且适配器方法被标记为private
( 它不是,但是如果 )呢? 由于无法覆盖该方法,因此您可以( 是的,您可以 )在其类中更改适配器代码,或者将代码复制并粘贴到您自己的适配器类中,从而有效地将类的99%复制到改变一个单一的函数调用。 每当有这个适配器的更新时,你要么会失去你的改变,要么你不会得到它(如果你是c&pd的话)。 如果它被标记为protected
( 就像它 ),你可以写一个pConnectAdapter子类。
而且,在inheritance的时候,你有效地说subClass 是一个 parentClass。 因此,你可以期望派生类具有与parentClass相同的function。 如果parentClass中有不应该在子类中可用的function,则从概念上禁用它属于子类。
这就是为什么我觉得把所有方法和属性都默认为protected
可见性要好得多,并且只标记那些方法(不是属性),而这些方法应该允许我的类从另一个类或脚本与public
类交互,但只有一些private
东西。 这样,我给开发者select使用我的课,因为我打算使用它,并select调整它。 如果他在这个过程中打破了一些东西,那很可能是他的错,而不是我的。
更新:自从我四年前写这篇文章以来,我得出结论,违约的事情要保护,而不是私人的,往往导致次优的子类。 这是因为人们会开始使用你提供的任何东西作为保护。 这又意味着你必须将所有这些方法都视为API,并且不能随意更改。 因此,最好仔细考虑要提供哪些扩展点,并保持其他所有内容的私密性。 请参阅http://fabien.potencier.org/article/47/pragmatism-over-theory-protected-vs-private以获得相似的观点。;
我通常会从最低层开始。 如果你不确定是否保密。 然后根据需要,您可以将事情保护或公开。
这个想法从私人到保护并不是一个突破性的变化,但它可能是一个突破性的改变,走向另一个方向。
不要认为私人/保护/公共事物就好像程序员会“需要”一种方法一样。 想想就好像你想允许他们访问它。
如果您认为应该允许更改数据库连接string,请将其公开。
我总是使所有的方法private
作为默认。 这是为了保持界面清洁,易于维护。
改变或隐藏一个已经可见的方法要比使私有方法更加明显更难。 至less如果您需要与现有的客户端代码兼容。
换句话说,我怎么可以事先知道客户端程序员永远不需要重写一个方法?
如果你不知道,他们将需要。 如果你没有问题(即,如果你认为他们应该能够),那么使用protected
; 否则使用private
。
私人成员被用来封装class级的内部运作。 使用它们来保存只有您想要访问的数据。 例如,假设您有一个名为_name的字段和一个名为GetName()/ SetName(名称)的getter / setter。 在允许SetName成功之前,您可能希望对名称进行语法检查,否则会抛出exception。 通过将_name设置为private,可以确保在对name进行任何更改之前都会进行语法检查(除非您自己的代码中更改了_name)。 通过保护它,你对class上任何潜在的未来的inheritance者说:“继续前进,和我的领域相处。
一般来说,保护措施只适用于特殊情况。 例如,你可能有一个受保护的构造函数,它为子类提供了一些额外的构造function。
当我需要从基类中调用它时,我通常只是把所有东西都private
并重构。
除了当我感到懒惰,做一切protected
,这不是绝对危险的。