All*_*nde 71
你应该使用受保护的成员变量吗?
取决于你对隐藏状态的挑剔程度.
如果开发人员出现并将您的类子类化,他们可能会搞砸,因为他们不完全理解它.对于除公共界面之外的私有成员,他们无法看到实现方式的实现具体细节,这使您可以灵活地在以后更改它.
Wil*_*ean 30
现在普遍的感觉是它们导致派生类和它们的基础之间的过度耦合.
它们与受保护的方法/属性相比没有特别的优势(曾几何时它们可能具有轻微的性能优势),并且它们也被用于更深层次的继承时尚的时代,而现在还没有.
Ori*_*rds 29
一般来说,如果某些东西不是故意设想为公开的,我会把它私有化.
如果出现需要从派生类访问该私有变量或方法的情况,我将其从private更改为protected.
这几乎不会发生 - 我真的不是所有继承的粉丝,因为它不是模拟大多数情况的特别好的方法.无论如何,继续,不用担心.
对于大多数开发人员来说,我说这很好(也许是最好的方法).
问题的简单事实是,如果其他开发人员一年后出现并决定他们需要访问您的私有成员变量,他们只需编辑代码,将其更改为受保护,并继续他们的业务.
唯一真正的例外情况是,如果您的业务是以黑盒形式将二进制dll发送给第三方.这基本上包括Microsoft,那些"Custom DataGrid Control"供应商,以及可能带有可扩展性库的其他一些大型应用程序.除非你属于那个类别,否则不值得花时间/精力去担心这类事情.
一般情况下,我会将受保护的成员变量保留在极少数情况下,您可以完全控制使用它们的代码.如果您正在创建公共API,我会说永远不会.下面,我们将成员变量称为对象的"属性".
这是你的超类在使成员变量受保护而不是私有访问者后不能做的事情:
在阅读该属性时,懒惰地创建一个值.如果添加受保护的getter方法,则可以懒惰地创建值并将其传回.
知道何时修改或删除了该属性.当超类对该变量的状态做出假设时,这可能会引入错误.为变量创建受保护的setter方法可以保持该控制.
在读取或写入变量时设置断点或添加调试输出.
重命名该成员变量,而不搜索可能使用它的所有代码.
一般来说,我认为我建议制作受保护的成员变量是极少数情况.最好花几分钟时间通过getter/setter暴露财产,而不是几小时后追踪修改受保护变量的其他代码中的错误.不仅如此,您还可以避免在不破坏相关代码的情况下添加未来的功能(例如延迟加载).现在做这件事要比现在做得更难.
在设计级别,使用受保护的属性可能是合适的,但是对于实现,我认为将其映射到受保护的成员变量而不是accessor/mutator方法没有任何优势.
受保护的成员变量具有明显的缺点,因为它们有效地允许客户端代码(子类)访问基类类的内部状态.这可以防止基类有效地维护其不变量.
出于同样的原因,受保护的成员变量也使编写安全的多线程代码变得更加困难,除非保证不变或局限于单个线程.
Accessor/mutator方法在维护时提供了更多的API稳定性和实现灵活性.
此外,如果您是OO纯粹主义者,则对象通过发送消息进行协作/通信,而不是读取/设置状态.
作为回报,它们提供的优势很少.我不一定会从其他人的代码中删除它们,但我不会自己使用它们.
对我来说,关键问题是,一旦你对变量进行了保护,你就不能允许你的类中的任何方法依赖于它在一个范围内的值,因为子类总是可以将它放在范围之外.
例如,如果我有一个定义可渲染对象的宽度和高度的类,并且我使这些变量受到保护,那么我就不能对(例如)宽高比做出任何假设.
至关重要的是,从代码作为库发布的那一刻起,我就永远无法做出这些假设,因为即使我更新我的setter以保持宽高比,我也无法保证变量是通过setter设置的,也可以通过现有代码中的getter.
我的类的任何子类也不能选择保证,因为它们也不能强制执行变量值,即使这是它们子类的整个点.
举个例子:
通过将变量约束为私有,我可以通过setter或getter强制执行我想要的行为.
仅供记录,在“Exceptional C++”第 24 项下的一个脚注中,Sutter 说道“你永远不会编写一个具有公共或受保护成员变量的类。对吗?(不管某些库设置的糟糕示例如何) .)”
| 归档时间: | 
 | 
| 查看次数: | 61304 次 | 
| 最近记录: |