代码之家  ›  专栏  ›  技术社区  ›  luvieere

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

  •  1
  • luvieere  · 技术社区  · 14 年前

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

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

    6 回复  |  直到 12 年前
        1
  •  2
  •   BitKFu    14 年前

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

    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
  •  4
  •   Oded    14 年前

    如果有一个常量需要是公共的,那么最好将其设置为公共字段,而不是为其创建getter属性。

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

    它们存在并被允许,因为有时候你需要灵活性。

        3
  •  1
  •   Matthias Meid    14 年前

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

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

    从设计的角度来看,我不知道在哪里推荐使用字段…

    干杯 马蒂亚斯

        4
  •  1
  •   soulmerge    14 年前

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

    你的问题现在可以形成 我总是想要这种行为吗? 我可以想到这样的情况:结构 struct C)。通过A parameter object 或者一个类,包装要插入到 Collection 在实际不需要访问器的情况下:对象只是变量的容器。

        5
  •  1
  •   Didier Trosset    14 年前

    使用get而不是public字段的原因只有一个:惰性评估。也就是说,您想要的值可能存储在数据库中,或者可能需要很长时间来计算,并且不希望您的程序在启动时初始化它,但只在需要时才初始化。

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

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

    如果要公开对象中字段的值,则公开它! 创建一个具有四个独立字段的对象,并要求所有字段都使用get/set或properties访问,这是完全没有意义的。

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

        6
  •  0
  •   Jon Hanna    14 年前

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

    实际上,从OOP的立场上,我们可以认为字段比“盲”属性更好,因为缺少封装比假装封装然后将其吹走的东西更清楚。如果封装是很重要的,那么最好看看什么时候不存在。

    一个名为foo的属性从外部不会被视为一个名为foo的公共字段。在某些语言中,这是显式的(语言不直接支持属性,因此您有一个getfoo和一个setfoo),在某些语言中,它是隐式的(c和vb.net直接支持属性,但它们与字段不二进制兼容,如果字段更改为属性,则编译为使用字段的代码将中断,反之亦然)。

    如果foo只是对底层字段进行“盲”设置和写入,那么 目前 与暴露字段相比,它没有封装优势。

    但是,如果以后需要利用封装来防止无效值(您应该始终防止无效值,但可能在第一次编写类时没有意识到某些地方无效,或者“valid”随作用域更改而更改),则需要包装Memoised计算,触发对象中的其他更改,而不是rigger-an-on-change事件,为了防止昂贵的、不必要的等价集等,那么在不破坏运行代码的情况下就无法进行更改。

    如果类是所讨论的组件内部的,这不是一个问题,如果字段在一般的Yagni原则下被明智地读取,我会说使用字段。但是,Yagni在组件边界上的表现不太好(如果我今天确实需要我的组件来工作,我肯定 可能需要在明天你改变了我的组件之后它才能工作,所以预先使用属性是有意义的。