OO:在类内部,是否应该通过属性来访问私有变量?

4

我在想,什么是良好的实践:

 private int value;

 public int Value { get { return this.value; } }

 private int DoSomething()
 {
      return this.Value + 1;
      //OR
      return this.value + 1;
 }

因此,问题是关于您应该如何处理您的类变量。您应该通过属性访问它们还是直接访问?


1
请参考以下链接:https://dev59.com/nnRB5IYBdhLWcg3wa2q2 - Andres
这个问题之前已经被问过几次: https://dev59.com/rEbRa4cB1Zd3GeqPzVVD, https://dev59.com/WkjSa4cB1Zd3GeqPD0OH, https://dev59.com/LnVC5IYBdhLWcg3whBaj. - Jeff Sternal
8个回答

8

在这种情况下,这并不是很重要,但是当您使用延迟加载变量时,这将非常重要,并且您需要通过属性进行访问。例如:

private Myobject _value;

public Myobject Value
{
    get
    {
        if (_value == null) _value = new MyObject();
        return _value;
    }
}

private MyObject DoSomething();
{
    //If you access _value here, it might be null...
    //so you should access it through the property:
    return Value;
}

在直接调用属性的情况下,如果你的方法失败了,你要么妥善处理它,要么通过更清晰的方式——通过你的属性来访问它。
关键在于你的应用程序的架构,因此你必须问一个问题:从维护的角度来看,什么是最有意义的?
我必须说,如果字段被正确初始化并且直接访问不会引起麻烦,那么就直接访问它。如果它导致额外的工作(因此需要额外的维护),则使用属性引用它。
像其他任何事情一样,权衡利弊。运用你自己的常识——标准之争是一个荒谬的分心。除非他们提供了你自己没有想到的论点,否则不要浪费时间与他们争吵。如果你有一个有效的理由选择任何你选择的路径,那么这条路就是正确的——这取决于设计者的特权。
我的优缺点思考如下:
使用属性:
- 我可以更改返回该值的实现而无需重构整个类。 - 我可以懒加载该值,这意味着如果我从未访问它,它永远不会浪费资源。 - 我可以将所有返回值实现的详细信息隐藏在一个地方,而不必在我的代码中处理它们。
使用字段:
- 在每次访问该值时,我没有步进属性代码的潜在性能开销。 - 我需要确保该值在每次调用时都被正确初始化,或处理它未被初始化的情况。 - 即使我的属性只提供只读接口,我仍然可以影响该值。
所以我想我的方法是使用属性,除非我需要直接写入值,在这种情况下,我会使用字段——因为我的属性是只读的,因此不能被写入。
当然这只是我的看法——你的属性可能是可读/可写的,你可能会从设计角度决定直接访问字段是可以的——这也是可以的。
关键是始终有理由做事情,不要盲目地做事情

2
我会选择直接访问。这完全是“家庭内部的事”,可以这么说。

1

这是标准之争的焦点。通常情况下,这不会有太大的影响,我只是在类内直接访问变量,除了 getters 和 setters 之外,它们执行的操作超出了仅仅获取或设置值。

问题在于你必须知道 getters 和 setters 在做什么,或者你必须始终将它们限制为简单操作而没有其他功能。


1

属性被引入来“隐藏”比从字段返回单个值更复杂的结构。

我建议您在所有代码中使用属性而不是字段,这样如果属性代码以后变得更加复杂,您就不需要重构类的其余部分。


0

我认为这不是一个非黑即白的问题。有几件事情需要考虑:

首先,如果属性没有行为(即get/set只是通过获取和返回字段),那么将该字段变成自动属性并消除困境。代码行数更少,没有混淆。

其次,如果属性具有副作用(延迟加载、更改通知、统计信息收集等),则必须考虑是否适合通过私有更新触发该行为。如果适当,就使用该属性。如果不适当,则不要使用(或更改设计使其更明显)。

此外,在适当的情况下,您始终可以引入包装器类型以消除混淆,如果这非常重要。

例如,假设您有一个由参数检查保护的角度属性。

public class ManThatCanRotate
{
    public int Angle 
    { 
       get { return m_angle; } 
       set { if(value >= 0 && value < 360) m_angle = value; }
    }

    public void RotateLikeSomeKindOfLunatic()
    {
       // imagine this has been called 359 times already.
       m_angle++; // ruh-roh
    }
}

如果您直接设置m_angle,将会发生不好的事情(tm);角度将变得无效。您可以将角度重构为自己的类型,以使其不可能无效,从而消除问题。


0

我投票支持返回 this.value + 1。

反对这种方法(即通过属性)的论点是,您可能希望稍后向属性方法添加额外的代码,因此如果您这样做,需要进行的更改较少。但我认为属性应该只按照广告所说的那样做,不多不少;也就是说,它们应该尽力返回该值。


0
在某些情况下这是一个好主意。例如,在 iPhone 的情况下,由于内存较低,您可能会收到来自操作系统的“内存警告”。根据这些警告,您被要求释放内存以避免被关闭。通常,这种内存来自像图像、声音或大数据块这样的资源,这些资源不需要连续存在于内存中。
在这种情况下,我有时会通过 Objective-C 私有访问器访问一些私有 ivars,这些访问器通常会检查 ivar 是否为“nil”(NULL),并以“懒加载”的方式将数据重新加载到内存中。对此,我发现私有属性非常有用。否则,我使用直接 ivar 访问。
像往常一样,我认为这个问题没有明确的答案:“这取决于情况”。

0
如果你的类不能信任自己的方法来访问自己的私有变量,那么它还能信任谁呢?

它不是不信任自己的方法,而是未来的开发者 :P - BenAlabaster
但是,在你精心设计的类方法中使用大量的访问器方法并不能阻止未来的开发人员直接触碰你的私有部分,不是吗? - David R Tribble

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接