在什么情况下应该使用公共字段而不是属性?

时间:2010-08-17 08:45:42

标签: oop encapsulation public-fields

  

可能重复:
  Public Data members vs Getters, Setters

在什么情况下应该使用公共字段,而不是属性或getter和setter方法(不支持属性)?它们的用途究竟在哪里,为什么,或者如果不是,为什么它们仍被允许作为语言功能?毕竟,它们打破了面向对象的封装原则,允许和鼓励使用getter和setter。

6 个答案:

答案 0 :(得分:4)

如果你有一个需要公开的常量,你也可以把它变成一个公共字段,而不是为它创建一个getter属性。

除此之外,就良好的OOP原则而言,我认为没有必要。

他们在那里并被允许,因为有时你需要灵活性。

答案 1 :(得分:2)

这很难说,但在我看来,公共字段仅在使用结构时才有效。

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/

答案 2 :(得分:1)

如果编译器没有优化getter和setter调用,则对属性的访问可能比读取和写入字段(调用堆栈)更昂贵。如果您执行许多调用,这可能是相关的。

但是,说实话,我不知道这是真的。至少在.NET和Java中,这都得到了很好的优化。

从设计的角度来看,我不知道建议使用字段的情况......

干杯 的Matthias

答案 3 :(得分:1)

让我们首先看一下为什么我们需要访问器(getter / setter)?你需要它们能够在分配新值/读取值时覆盖行为。您可能希望添加缓存或返回计算值而不是属性。

你的问题现在可以形成为我是否总是想要这种行为?我可以想到这根本没用的情况:结构(C中的struct是什么) 。传递一个parameter object或一个包含多个要插入Collection的值的类是一个实际上不需要访问器的情况:该对象只是变量的容器。

答案 4 :(得分:1)

有一个原因(*)为什么要使用get而不是public field:lazy evaluation。即您想要的值可能存储在数据库中,或者计算时间可能很长,并且不希望程序在启动时初始化它,但仅在需要时才会初始化。

有一个原因(*)为什么要使用set而不是public field:其他字段修改。即当目标字段的值发生更改时,您可以更改其他字段的值。

强制在每个字段上使用get和set,YAGNI原则相矛盾。

如果你想从一个对象公开一个字段的值,然后公开它!创建一个具有四个独立字段的对象并强制所有它们都使用get / set是完全没有意义的或属性访问。

*:可能的数据类型更改等其他原因毫无意义。事实上,无论您使用a = o.get_value()而不是a = o.value,如果您更改get_value()返回的类型,则必须在每次使用时更改,就像您更改了{的类型一样{1}}。

答案 5 :(得分:0)

主要原因与OOP封装无关(虽然人们经常说它是),而且与版本控制有关。

事实上,从OOP的立场来看,字段比“盲”属性更好,因为缺乏封装比假装封装然后将其吹走更清楚。如果封装很重要,那么看它何时不存在应该是很好的。

一个名为Foo的属性在外部不会被称为Foo的公共字段。在某些语言中,这是显式的(语言不直接支持属性,因此你有一个getFoo和一个setFoo),而在某些语言中它是隐式的(C#和VB.NET直接支持属性,但它们不是二进制兼容的编译为使用字段的字段和代码如果更改为属性将会中断,反之亦然。

如果您的Foo只是进行“盲”设置并写入基础字段,那么当前没有封装优势来覆盖该字段。

但是,如果以后需要利用封装来防止无效值(你应该总是防止无效值,但是你可能没有意识到在你第一次写这个类时有些无效,或者可能是“有效”)已更改范围更改),包装记忆评估,触发对象中的其他更改,触发更改事件,防止昂贵的不必要的等效集等等,然后您不能在不破坏的情况下进行更改运行代码。

如果该类是相关组件的内部,那么这不是一个问题,如果字段在一般的YAGNI原则下明确读取,我会说使用字段。但是,YAGNI在组件边界上的表现并不是那么好(如果我确实需要我的组件在今天工作,我肯定可能需要在你改变你的组件后明天才能工作我的依赖),所以先发制人地使用属性是有意义的。