如果我正在写一个课程,我何时将方法设为私有,而不是保护?换句话说,我怎么能预先知道客户端程序员永远不需要覆盖方法?在某种情况下,它有外部因素,如数据库连接?
Ale*_*own 51
public和protected方法形成对象的"接口",public对于使用(委托)您的类protected的开发人员,以及希望通过子类化来扩展对象功能的开发人员.
请注意protected,即使您的类将被子类化,也没有必要提供方法.
两者public和protected接口都需要仔细考虑,特别是如果这是一个供您控制之外的开发人员使用的API,因为对接口的更改可能会破坏对现有接口如何工作的假设的程序.
private 方法纯粹是为了对象的作者,可以随意重构,更改和删除.
我会private默认使用,如果你发现需要暴露更多方法,请仔细考虑如何使用它们 - 特别是如果它们是虚拟的 - 如果它们被另一个开发人员完全替换为任意替代函数会发生什么你的班级还能上班吗?然后设计一些适合protected开发人员对您的对象进行子类化(如果需要),而不是公开现有函数.
Gor*_*don 26
换句话说,我怎么能预先知道客户端程序员永远不需要覆盖方法?
你不能.你不需要.如果开发人员可能想要覆盖方法,那么预测不是你的工作,更不用说如何了.只是假设他想要并且无需触摸您的代码即可让他这样做.因此,private如果您不需要,请不要声明方法.
如果开发人员认为他需要调整类的某些功能,他可以从许多结构和行为模式中进行选择,例如装饰器,适配器或通过子类化.使用这些模式很好,因为它将更改封装到开发人员自己的类中,并保持自己的代码不变.通过声明方法private,您可以确保开发人员会在您的课程中使用.这很糟糕.
一个完美的例子是Zend Framework的DB适配器.他们不鼓励使用持久连接,并且它们的适配器没有为此提供任何手段.但是,如果你想要这个并且适配器方法被标记private(它不是,但是如果)会怎么样?由于无法覆盖该方法,您可以(是的,您可以)在其类中更改适配器代码,或者将代码复制并粘贴到您自己的适配器类中,从而有效地复制99%的类.更改单个函数调用.每当有适配器更新时,您可能会丢失更改,或者您无法获得更改(如果您使用c&p).如果它被标记protected(实际上),你可以编写一个pConnectAdapter子类.
而且,在子类化时,你实际上是在说subClass 是一个 parentClass.因此,您可以期望派生类具有与parentClass相同的功能.如果parentClass中的功能在subClass中不可用,则在概念上禁用它属于subClass.
这就是为什么我发现将所有方法和属性默认为protected可见性并且仅标记那些应该允许从另一个类或脚本与我的类进行交互的方法(但不是属性)更好的做法public,但只有少数事情private.这样,我给开发人员选择使用我的类,因为我打算使用它和调整它的选项.如果他在这个过程中打破了某些东西,那很可能是他的错,而不是我的.
更新:自从我四年前写这篇文章以来,我得出的结论是,将事务默认为保护而非私有通常会导致次优的子类.这是因为人们会开始使用你提供的任何保护.这反过来意味着您必须将所有这些方法视为API,并且可能不会随意更改它们.因此,最好仔细考虑您想要提供的扩展点,并将其他所有内容保密.有关类似视图,请参见http://fabien.potencier.org/article/47/pragmatism-over-theory-protected-vs-private.