1

可能重复:
公共数据成员与 Getter、Setter

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

4

6 回答 6

4

如果您有一个需要公开的常量,您不妨将其设为公开字段,而不是为其创建 getter 属性。

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

它们在那里并且被允许,因为有时您需要灵活性。

于 2010-08-17T08:49:56.027 回答
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/

于 2010-08-17T08:58:45.267 回答
1

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

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

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

干杯马蒂亚斯

于 2010-08-17T08:52:37.243 回答
1

我们先来看看为什么我们需要访问器(getter/setter)这个问题?您需要它们能够在分配新值/读取值时覆盖该行为。您可能想要添加缓存或返回计算值而不是属性。

你的问题现在可以形成,因为我总是想要这种行为?我可以想到这根本没有用的情况:结构(structC 中的 s 是什么)。传递参数对象或包装多个值的类以插入到集合中是实际上不需要访问器的情况:对象只是变量的容器。

于 2010-08-17T08:59:59.310 回答
1

使用 get 而不是 public 字段只有一个原因(*):惰性求值。即您想要的值可能存储在数据库中,或者计算时间可能很长,并且不希望您的程序在启动时对其进行初始化,但仅在需要时进行。

使用 set 而不是 public 字段只有一个原因(*):其他字段修改。即,当您更改目标字段的值时,您会更改其他字段的值。

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

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

*:其他原因如可能的数据类型改变是没有意义的。事实上,无论你在哪里使用a = o.get_value()而不是a = o.value,如果你更改返回的类型,get_value()你必须在每次使用时更改,就像你会更改 的类型一样value

于 2010-08-17T09:08:11.597 回答
0

主要原因与 OOP 封装无关(尽管人们经常这么说),而与版本控制有关。

事实上,从 OOP 的立场来看,人们可能会争辩说字段比“盲目”属性更好,因为缺乏封装比假装封装然后将其吹走的东西更清楚。如果封装很重要,那么最好看看它什么时候不存在。

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

如果您的 Foo 只是对底层字段进行“盲目”设置和写入,那么目前与公开该字段相比没有封装优势。

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

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

于 2010-08-17T09:21:41.580 回答