干净代码建议在“格式”一章的“垂直距离”部分中避免使用受保护的变量:
紧密相关的概念应在垂直方向上彼此靠近。显然,此规则不适用于属于单独文件的概念。但是,除非您有充分的理由,否则不应将紧密相关的概念分成不同的文件。确实,这是应避免使用受保护变量的原因之一。
这是什么原因?
干净代码建议在“格式”一章的“垂直距离”部分中避免使用受保护的变量:
紧密相关的概念应在垂直方向上彼此靠近。显然,此规则不适用于属于单独文件的概念。但是,除非您有充分的理由,否则不应将紧密相关的概念分成不同的文件。确实,这是应避免使用受保护变量的原因之一。
这是什么原因?
Answers:
应避免使用受保护的变量,因为:
但是正如您所看到的,所有这些都是“倾向于”的。有时,受保护的成员是最优雅的解决方案。受保护的功能往往很少出现这些问题。但是有很多事情使他们受到谨慎对待。任何需要这种照顾的事情,人们都会犯错,而在编程世界中,这将意味着错误和设计问题。
我还没有读过这本书,但是我可以刺破鲍伯叔叔的意思。
如果穿上protected
某些东西,则意味着一个类可以继承它。但是成员变量应该属于它们所包含的类。这是基本封装的一部分。放入protected
成员变量会破坏封装,因为现在派生类可以访问基类的实现详细信息。当您public
在普通类上创建变量时,也会发生相同的问题。
要解决此问题,可以将变量封装在一个受保护的属性中,如下所示:
protected string Name
{
get { return name; }
private set { name = value; }
}
这允许name
使用构造函数自变量从派生类中进行安全设置,而无需暴露基类的实现细节。
protected
public
BaseType
DerivedType
BaseType
BaseType
protected
DerivedType
base
base
BaseType
这里已经有一些非常好的答案。但要添加的一件事:
在大多数现代的OO语言中,将每个类放入自己的文件中是一个好习惯(在Java AFAIK中是必要的)(请不要对C ++有所了解,因为C ++中经常有两个文件)。
因此,实际上不可能将函数保留在派生类中,并使源代码中的基类的受保护变量在源代码中“垂直接近”变量定义。但是理想情况下应将它们保留在此,因为受保护的变量是供内部使用的,这使得使用它们的函数通常是“紧密相关的概念”。
基本思想是,声明为“保护”的“字段”(实例级变量)可能比它必须的可见,而“保护”的程度比您想要的少。C / C ++ / Java / C#中没有访问修饰符,该修饰符等同于“只能由同一程序集中的子类访问”,因此使您能够定义自己的子程序,这些子程序可以访问程序集中的字段,但是不允许在其他程序集中创建的子级具有相同的访问权限;C#具有内部修饰符和受保护的修饰符,但是将它们组合在一起可使访问成为“内部修饰符”,而不是“内部修饰符”。因此,无论您写的是该孩子还是其他人,任何孩子都可以访问受保护的字段。因此,受保护成为黑客的门户。
同样,根据字段的定义,更改字段时几乎没有固有的验证。在C#中,您可以使一个只读,从而使值类型有效地保持不变,并且引用类型无法重新初始化(但仍然非常可变),仅此而已。这样,即使受到保护,您的孩子(您不能信任)也可以访问此字段并将其设置为无效字段,从而使对象的状态不一致(应避免使用)。
公认的使用字段的方法是将它们设置为私有并使用属性和/或getter和setter方法访问它们。如果该类的所有消费者都需要该值,则(至少)将获取者公开。如果只有孩子需要,请保护吸气剂。
回答问题的另一种方法是问自己。为什么子方法中的代码需要直接修改我的状态数据的能力?那关于那个代码怎么说?那是表面上的“垂直距离”参数。如果子代中有必须直接更改父代状态的代码,那么也许该代码应该首先属于父代?
这是一个有趣的讨论。
坦率地说,好的工具可以缓解许多这些“垂直”问题。实际上,在我看来,“文件”的概念实际上阻碍了软件开发-Light Table项目正在努力解决这一问题(http://www.chris-granger.com/2012/04/12/light-表格---新概念/)。
将文件从图片中删除,受保护的范围变得更具吸引力。受保护的概念在SmallTalk之类的语言中变得最为清晰-任何继承都只是扩展了类的原始概念。它应该做所有并拥有父类所做的一切。
我认为,类层次结构应尽可能浅,大多数扩展来自组合。在这样的模型中,我看不出有任何理由导致私有变量不被保护。如果扩展类应该表示包括父类的所有行为的扩展(我认为应该如此,因此认为私有方法本质上是不好的),那么扩展类为什么也不能表示此类数据的存储呢?
换句话说,在任何我认为私有变量比受保护变量更适合的情况下,继承都不是解决问题的方法。
如此处所说,这只是原因之一,即逻辑链接的代码应放在物理链接的实体(文件,程序包和其他)中。在较小的规模上,这与您没有放置一个类的原因相同,该类使具有显示UI的类的数据库查询进入程序包。
但是,不建议使用受保护的变量的主要原因是因为它们倾向于破坏封装。变量和方法应具有尽可能有限的可见性;有关更多参考,请参见Joshua Bloch的有效Java条款 13-“最小化类和成员的可访问性”。
但是,您不应将所有这些广告都当作公会来使用;如果受保护的变量非常糟糕,则它们根本不会放在语言中。imho保护字段的合理位置是在测试框架的基类内部(集成测试类对其进行了扩展)。