应该在什么情况下使用公共字段来代替属性?
可能重复:
Public Data members vs Getters, Setters应该在什么情况下使用公共字段来代替属性?
在何种情况下应公共字段被用来替代性或getter和setter方法(这里有对性能没有支持),?建议他们的用途,以及为什么,或者如果不是,他们为什么仍然被允许作为语言功能?毕竟,它们打破了面向对象的封装原则,在这个原则中允许和鼓励获取者和设置者。
这很难说,但在我看来,公共领域使用结构时,才有效。
struct Simple
{
public int Position;
public bool Exists;
public double LastValue;
};
但是,不同的人对不同的想法:
http://kristofverbiest.blogspot.com/2007/02/public-fields-and-properties-are-not.html
http://blogs.msdn.com/b/ericgu/archive/2007/02/01/properties-vs-public-fields-redux.aspx
http://www.markhneedham.com/blog/2009/02/04/c-public-fields-vs-automatic-properties/
如果您有一个需要公开的常量,那么您不妨为其创建一个公共字段而不是为其创建一个getter属性。
除此之外,就好的面向对象原则而言,我并不认为有必要。
他们在那里,因为有时你需要灵活性。
+1阅读我的想法:) – 2010-08-17 08:50:58
我不确定公共常数是否总是可取的。从这一点开始,这样一个值就是API的一部分,您可能无法轻易删除/修改它。 – soulmerge 2010-08-17 09:02:50
如果您的编译器不优化getter和setter调用,对您的属性的访问可能比读写字段(调用堆栈)更昂贵。如果执行很多很多的调用,这可能是相关的。
但是,说实话,我不知道这是真的语言。至少在.NET和Java中都是这样优化的。
从设计的角度来看,我知道没有地方建议使用领域的情况下...
干杯 马蒂亚斯
让我们先来看看这个问题为什么我们需要存取(getter/setter方法) ?您需要他们能够覆盖分配新值/读取值时的行为。您可能想要添加缓存或返回计算值而不是属性。
您的问题现在可以形成为我是否总是想要这种行为?我可以想到这种情况根本没有用:结构(在C中是struct
s)。传递一个parameter object或一个包装多个值以插入Collection的类是实际不需要访问器的情况:该对象仅是变量的容器。
有一个原因(*)为什么使用get而不是公共领域:懒惰评估。即您想要的值可能会存储在数据库中,或者可能需要很长时间才能计算,并且不希望程序在启动时对其进行初始化,但仅在需要时进行初始化。
有一个原因(*)为什么要使用set而不是public field:其他字段的修改。即当目标字段的值发生更改时,您可以更改其他字段的值。
强制使用get和set每个字段都在与YAGNI原理矛盾。
如果你想从一个对象暴露一个字段的值,然后将其暴露!创建一个具有四个独立字段的对象并强制所有对象都使用get/set或properties访问是毫无意义的。
*:其他原因,如可能的数据类型更改是毫无意义的。事实上,无论你使用a = o.get_value()
代替a = o.value
,如果更改get_value()
你必须在每次使用改变,就好像你会改变类型的value
返回的类型。
我不认为YAGNI只是“当我们发布这个组件的更高版本时可能不需要调用代码”。我很确定他们会需要它,所以您必须考虑是否需要预先将字段更改为属性,因为这样的更改会打破调用代码。 – 2010-08-17 09:24:53
就像你写的那样,你很确定*。 YAGNI说,除非你真的需要它,否则你不会写。 – 2010-08-17 11:20:17
我说幽默价值“非常确定”。我100%肯定地说,如果我升级一个组件并且许多其他组件停止工作,那我就不会开心。我不知道我是否需要一个特定的改变,但如果不能在不破坏运行代码的情况下做出改变,那么YAGNI就有限制。 – 2010-08-17 11:22:51
主要的原因是没有与OOP的封装做(尽管人们常说它是),以及一切与版本控制。
事实上从OOP位置可认为,字段是不是“盲目”性能更好,因为缺乏封装比的东西,假装封装更清楚,然后吹它拿走。如果封装很重要,那么应该很高兴看到它不在那里。
称为富的属性不会被视为从外面一样叫Foo的公共领域。在某些语言中,这是明确的(语言不直接支持属性,所以你有一个getFoo和一个setFoo),在某些语言中它是隐式的(C#和VB.NET直接支持属性,但它们不是二进制兼容的如果将字段和代码编译为使用字段,则会将其更改为属性,反之亦然)。
如果你的Foo只是做了一个“盲目”设置和写入一个底层字段,那么目前有没有封装优势来暴露这个字段。但是,如果以后需要利用封装来防止无效值(您应该始终防止无效值,但是您可能没有意识到某些位置在第一次写入该类时无效,或者可能“有效“随着范围变化而改变),包装记忆评估,触发对象中的其他变化,触发电流变化事件,防止昂贵的不必要的等效集合等等,然后不能进行更改破坏运行代码。
如果类是内部的问题组件,这不是一个问题,我想说的使用领域,如果场下的一般原则YAGNI阅读理智。然而,YAGNI在组件边界上的表现并不那么出色(如果我确实需要我的组件在今天工作,我当然可能需要在明天改变你的组件后才能使用它),但是,所以先发制人地使用属性是有意义的。
至少在.net中,如果所讨论的类型是一个结构,其状态通过可以公开读取的属性/字段公开,并且可以通过构造函数设置,以接受任何有效值的组合它们各自的类型,特性几乎没有封装优点,但有明显的缺点。 – supercat 2012-11-28 20:30:21
我在.net中犯的另一个例外情况就像是'MutableHolder'类,其唯一目的是暴露一个类型为“T”的公共字段。当将这些类中的“Interlocked”兼容的集合项存储在集合中时,将它们包装在一起可以使用“Interlocked”方法,即使集合不支持这种情况,并且在这些类中封装值类型将允许他们被“直接”改变而不需要修改底层集合。通过使用暴露域PODS作为类型参数,可以在类对象中保存多个单个项目。 –
supercat
2012-11-28 20:28:11