我们是否应该使用受保护的成员变量?

时间:2020-03-05 18:45:42  来源:igfitidea点击:

我们是否应该使用受保护的成员变量?优点是什么?这可能导致什么问题?

解决方案

回答

Should you ever use protected member variables?

取决于我们对隐藏状态的挑剔程度。

  • 如果我们不希望任何内部状态泄漏,那么将所有成员变量都声明为私有是可行的方法。
  • 如果我们真的不关心子类可以访问内部状态,那么受保护就足够了。

如果开发人员出现并为类提供子类,则他们可能会弄乱它,因为他们无法完全理解。对于私有成员(除了公共接口),他们看不到具体的实现细节,这使我们以后可以灵活地对其进行更改。

回答

有关.Net访问修饰符的详细信息,请单击此处

受保护的成员变量没有实际的优点或者缺点,这是我们在特定情况下需要什么的问题。通常,将成员变量声明为私有变量并允许通过属性进行外部访问是公认的惯例。此外,某些工具(例如某些O / R映射器)期望对象数据由属性表示,并且无法识别公共或者受保护的成员变量。但是,如果我们知道希望子类(并且仅子类)访问某个变量,则没有理由不将其声明为受保护的变量。

回答

如今的普遍感觉是,它们在派生类和它们的基类之间造成了不适当的耦合。

与受保护的方法/属性相比,它们没有什么特别的优势(一次过,它们可能会有一点性能上的优势),而且它们还被用在一个非常深的继承成为时尚的时代,而现在还不是。

回答

简而言之,是的。

受保护的成员变量允许从任何子类以及同一包中的任何类访问变量。这可能非常有用,尤其是对于只读数据。我认为它们从来没有必要,因为可以使用私有成员变量以及几个getter和setter来复制对受保护成员变量的任何使用。

回答

通常,如果不是故意将某些内容视为公开的,则将其设为私有。

如果出现需要从派生类访问该私有变量或者方法的情况,则将其从私有更改为受保护。

这种情况几乎不会发生,我真的不是一个继承者,因为它不是建模大多数情况的特别好方法。无论如何,继续前进,无后顾之忧。

我会说这对大多数开发人员来说都是很好的方法(也许是最好的方法)。

问题的简单事实是,如果其他开发人员在一年后才出现并决定需要访问私有成员变量,他们将只是编辑代码,将其更改为受保护的代码并继续开展业务。

唯一真正的例外是,如果我们要以黑箱形式将二进制dll运送给第三方。它主要由Microsoft,那些"自定义DataGrid控件"供应商以及可能带有扩展库的其他一些大型应用组成。除非我们属于此类,否则不花时间/精力去担心这种事情是不值得的。

回答

在大多数情况下,使用protected是很危险的,因为我们可能会破坏类的封装,而这种封装很可能会被设计不良的派生类破坏。

但我有一个很好的例子:假设我们可以使用某种通用容器。它具有内部实现和内部访问器。但是我们至少需要提供对其数据的3种公共访问权限:map,hash_map,类似矢量。然后,我们将得到以下内容:

template <typename T, typename TContainer>
class Base
{
   // etc.
   protected
   TContainer container ;
}

template <typename Key, typename T>
class DerivedMap     : public Base<T, std::map<Key, T> >      { /* etc. */ }

template <typename Key, typename T>
class DerivedHashMap : public Base<T, std::hash_map<Key, T> > { /* etc. */ }

template <typename T>
class DerivedVector  : public Base<T, std::vector<T> >        { /* etc. */ }

我不到一个月前就使用了这种代码(因此代码来自内存)。经过一番思考,我相信尽管通用Base容器应该是一个抽象类,即使它可以很好地运行,因为直接使用Base会很痛苦,因此应予以禁止。

结束语因此,我们已保护派生类使用的数据。尽管如此,我们必须考虑到基类应该是抽象的事实。

回答

通常,在极少数情况下,即使我们完全控制使用它们的代码,我也会保留受保护的成员变量。如果我们要创建公共API,那我就说永不。下面,我们将成员变量称为对象的"属性"。

在将成员变量设置为受保护成员(而不是带有访问者的私有成员)之后,超类将无法执行以下操作:

  • 读取属性时,会懒惰地动态创建一个值。如果添加受保护的getter方法,则可以延迟创建值并将其传递回。
  • 知道何时修改或者删除属性。当超类对变量的状态进行假设时,这可能会引入错误。为该变量创建一个受保护的setter方法可以保留该控件。
  • 读取或者写入变量时设置断点或者添加调试输出。
  • 重命名该成员变量,而不搜索可能使用它的所有代码。

总的来说,我认为这是极少数情况,建议我们创建一个受保护的成员变量。我们最好花几分钟的时间通过getter / setter公开属性,而不是花费数小时后才通过其他代码修改受保护的变量来查找错误。不仅如此,还可以确保我们在不破坏相关代码的情况下添加将来的功能(例如延迟加载)。迟做比现在做起来难。

回答

在设计级别上,使用受保护的属性可能是合适的,但是对于实现而言,将其映射到受保护的成员变量而不是访问器/更改器方法没有好处。

受保护的成员变量具有明显的缺点,因为它们有效地允许客户端代码(子类)访问基类的内部状态。这阻止了基类有效地保持其不变性。

出于同样的原因,受保护的成员变量也使编写安全的多线程代码变得更加困难,除非保证常量或者将其限制在单个线程中。

访问器/更改器方法在维护下可提供更大的API稳定性和实现灵活性。

另外,如果我们是OO纯粹主义者,则对象通过发送消息(而不是读取/设置状态)来进行协作/通信。

作为回报,它们几乎没有优势。我不一定要将它们从其他人的代码中删除,但我自己不会使用它们。