Are protected members/fields really that bad?
现在,如果您阅读msdnforc中的命名约定,您会注意到它指出属性总是优先于公共和受保护的字段。有些人甚至告诉我,你不应该使用公共或受保护的土地。现在我同意我还没有找到一个理由,我需要一个公共领域,但保护领域真的那么糟糕吗?
我可以看到,如果您需要确保在获取/设置值时执行某些验证检查,但是在我看来,很多时候似乎只是额外的开销。我是说,假设我有一个类游戏项,其中包含basename、prefixname和suffixname字段。为什么我要承担创建属性(C#或访问器方法的开销,以及可能发生的性能损失(如果我对应用程序中的每个字段都这样做,我确信它加起来不会太多,特别是在某些语言(如PHP中)或某些具有性能的应用程序中,这是关键的,就像电子游戏?
Are protected members/fields really that bad?
不,是这样,更糟。
一旦一个成员比private更容易访问,您就可以向其他类保证该成员的行为。因为一个字段是完全不受控制的,所以将它"放在野外"将打开您的类和继承自类或与类交互的类,从而增加bug风险。无法知道字段何时更改,也无法控制字段的更改者或更改内容。
如果现在或者将来某个时候,您的任何代码曾经依赖于某个字段某个特定的值,那么您现在必须添加有效性检查和回退逻辑,以防它不是预期的值——您使用它的每个地方。当你本来可以把它变成一个该死的财产时,这是一个巨大的浪费。
与派生类共享信息的最佳方法是只读属性:
1
| protected object MyProperty { get; } |
如果你必须让它读/写,不要。如果你真的,真的必须让它读-写,重新考虑你的设计。如果你还需要读写,向你的同事道歉,不要再这样做了:)
很多开发人员相信——并且会告诉你——这是过于严格的。的确,你可以过得很好而不必这么严格。但采用这种方法将有助于您从勉强适应到非常健壮的软件。您将花费更少的时间来修复错误。
关于性能的任何问题-不要这样。我保证在你的整个职业生涯中,你永远不会以如此快的速度编写代码,以至于瓶颈是调用堆栈本身。
- +1,more if I could.当你做了一个非私人的成员时,你永远和它在一起。这是你的公共界面
- 我很同意,但我看没有问题有写保护性能。毕竟这只是一种方法的句法糖,有一个参数,我不认为很多人会争辩说,保护方法不一定有任何参数。(我不知道当选择一种方法和一种特性之间的缓慢语义差异。)
- @Daniel making a property writable address an order of magnity in complexity.在现实世界里,每一个阶级的定义都是不现实的,但如果你的班级中有很多,那就很容易写入错误的自由码。我曾经说过,我希望能帮助别人。
- @Daniel(to clarify,I am distincting between properties as representing State and methods representing actions)
- 我已经忘记了,财产可以容易地创造出来:保护内部的某些特性{Get;set}.I have a hard time understanding why property should never be writable.我的意思是,如果财产只能是阅读的,场地只能是私人的,那么,只有通过建筑物(除非我错过了一些东西)才能在一个新的类别中建立一个场地价值。我现在看到,为什么每次都要用公共/保护的财产(至少在C ;)来培养一个好的主意。
- 好吧,只是不变的广告类型。好东西,继续走!
- @Daniel(also to clarify,by immutable I mean externally immutable-that is,consumers can't infect the State.班级内部可能影响到它自己的国家。
- @Ryanzec you nailed it!消费者只有在初始化时才能确定一个物体的状态(通过建筑物)。一旦物体进入生命,它就应该对其自身的生命承担内部责任。Allowing consumers to impact the State adds unnecessary complexity and risk.
- @Daniel,No,protected writable property is about the worst design choice you can make.与遗产的过度积累相结合,这些迅速变成了一个夜晚。我看到人们在大型遗产链中保护变量。尝试在任何不容易的项目中解决这个问题。
- @Rex M根据你的初步评论(在我的评论之前我没有看到),我可以看到,只有读到的东西是好的。对我来说,这不是一个非常严格的指导方针(比如说,确保没有公共领域),而是一个不寻常的想法,认为它可以指导更好的规范设计。
- 我在Gamedev论坛上提出的问题中描述了这篇文章。Gamedev.stackexchange.com/questions/141326/…+1 for this answer for clearly stating advantages of this approach.
- Most of the issues are related to modifying the protected member.但如果它是一个const(我在C++的背景下问)?还是坏吗?
- 你是如何为保护和私有财产/方法创建单位的?
- @Frankm protected members are a contract between a superclass and its subclasses,so to interact with them,create derived classes in your tests.你不应该测试私人成员。
好的,投票否决时间。
其余的争论都以这种方式困扰着我:
他们听起来像是"威望之争"。如果msdn说了,或者某个大家都喜欢的著名开发人员或作者说了,那一定是这样。
它们基于这样一个理念,即数据结构具有许多不一致的状态,必须保护它们不受漫游或放置到这些状态中。因为(在我看来)数据结构在当前的教学中被过分强调,所以它们通常需要这些保护。更可取的是最小化数据结构,使其趋向于规范化,而不具有不一致的状态。然后,如果一个类的成员被更改,那么它只是被更改,而不是被损坏。毕竟,很多好的软件都是用C语言编写的,而这并没有因为缺少保护而遭受巨大的损失。
它们基于极端的防御编码。它基于这样一个理念:你的类将在一个没有人可以信任其他代码的世界中使用,而不是欺骗你的东西。我相信有些情况下这是真的,但我从未见过。我所看到的情况是,为了绕过不需要的保护,使事情变得非常复杂,并试图保护数据结构的一致性,这些数据结构过于复杂和不规范。
- 非常好的点数。我只想让一个想法变强:如果你在一队人以上的工作,那么你的密码就在野外。合同中没有明确规定的任何事情都很容易被误解。这是一个伟大的服务,通过消除模棱两可和通过设计加强信息流动来减少每个人的努力。
- 最重要的是,Python没有私密的方法,让我们独自保护自己,它不会变成一个真正的交易。
- @Rex:我知道这是接受的wisdom,而且我确信这一点,但它仍然像一些人相信抽象的东西一样,对我进行打击,而不是从艰难的经历中知道。我一直都知道如果你看上去像是在深深的信念下,你可以找到宝石。(BTW我在一个好队伍里工作)
- 也许大多数人只相信它是抽象的,但自从我开始生活,并为我的团队制定了政策以来,生活变得更加愉快。产量上升,错误率下降,幸福感上升。毫无疑问,以这种方式工作是一座难以攀登的小山。在我看来,这是值得的。
- @雷克斯:好的,不要竞争。
关于字段与属性,我可以考虑在公共接口中优先使用属性的两个原因(受保护的也是公共的,从某种意义上说,除了您的类之外,其他人也可以看到它)。
关于日常开支:
如果getter/setter是通常的一行代码,它只读取/设置字段的值,那么JIT应该能够内联调用,因此没有性能过剩。
当您使用自动实现的属性(C 3.0和更新版本)时,语法开销会大大减少,因此我认为这不是一个问题:
1
| protected int SomeProperty { get; set; } |
事实上,这使您可以很容易地使例如set受保护和get公开,因此这比使用字段更优雅。
公共字段和/或受保护字段是不好的,因为它们可以在声明类之外进行操作,而无需验证;因此可以说它们破坏了面向对象编程的封装原则。
当您失去封装时,您就失去了声明类的契约;您不能保证该类的行为符合预期或预期。
使用属性或方法访问字段使您能够维护封装,并完成声明类的约定。
它实际上取决于您的类是数据类还是行为类。
如果将行为和数据分开,那么可以公开数据类的数据,只要它们没有行为。
如果类是行为类,那么它不应该公开任何数据。
我同意只读属性答案。但要在这里扮演魔鬼的拥护者,这真的取决于你在做什么。我很高兴地承认,我一直在和公众成员一起编写代码(我也不发表评论,不遵守指导原则,也不做任何手续)。
但当我在工作的时候,情况就不同了。