【问题标题】:When should a class use its own getters/setters vs accessing the members directly?一个类什么时候应该使用自己的getter/setter而不是直接访问成员?
【发布时间】:2009-02-25 14:01:43
【问题描述】:

在 Eclipse 中生成 setter 和 getter 时,其中一个选项是在类中使用 getter 和 setter,而不是直接访问类成员。这种级别的类内部封装是有用的,还是把一个好主意走得太远了?

欺骗Should you use accessor properties from within the class, or just from outside of the class?

【问题讨论】:

标签: oop encapsulation


【解决方案1】:

我认为,如果您希望发生潜在的副作用 - 验证、日志记录等,这是一个好主意。(在 C# 中,我希望能够声明一个变量和属性,并说 only 通过属性访问变量。)

有时您可能会发现您需要直接设置变量,因为您想要副作用。例如,您可能需要同时设置两个变量,并且“之前”和“之后”状态都有效,但单独设置任何一个属性都会导致验证失败。

【讨论】:

    【解决方案2】:

    如果您允许派生类重新定义您的 getter,它会很有用。因此,即使在类内部使用 getter 也会使您的设计具有可扩展性。

    在我看来,这是需要在编码指南中定义的内容。

    【讨论】:

      【解决方案3】:

      简短的回答是“这取决于”:)

      Eric Lippert 在Automatic vs. Explicit properties 上有一篇很好的文章处理了这个问题,尽管角度略有不同。

      基本上,你需要问的问题是:

      “在类内部,访问此...属性的所需语义与从外部访问该属性所需的语义不同吗?”

      如果语义相同,您的类应该使用自己的属性。如果语义不同,您的类将需要直接操作支持字段。

      【讨论】:

        【解决方案4】:

        这很有用,例如,当您有设置者执行额外操作(例如设置脏标志或通知观察者)时。

        对于 getter,您可以在更改表示时计算一个值,而不是访问字段。

        【讨论】:

          【解决方案5】:

          当您需要扩展类的 getter/setter 行为时,封装字段(getter/setter 而不是直接成员访问)很有用。 然而在继承中,如果它的子类不应该知道它的私有内容,那么保留你的类的内部在概念上是很有趣的。因此,有时该字段对于类的实现来说是私有的,因此即使是子类也不知道它。

          【讨论】:

            【解决方案6】:

            我发现我有时会这样做 - 特别是当我需要或强烈预期我会需要一些登录以获取或设置(以及围绕它们进行验证)成员时。

            我发现在这些情况下,拥有私有/内部属性确实有帮助。

            但我肯定不会为任何成员这样做。

            最新的 .NET/VS 在这里确实很有帮助,因为您可以像这样声明一个属性:

            public string SomeProperty
            {
            get;
            set;
            }
            

            它有效地创建了幕后的 memebr。我知道这对您没有帮助,但我认为这可能会引起您的兴趣:-)

            【讨论】:

              【解决方案7】:

              如果您希望此成员可通过 Winform 或 WPF 进行数据绑定,我相信您需要将其声明为属性。我大约 95% 的肯定数据绑定需要一个属性(getter/setting 语法)。我有一个小型 wpf 解决方案来演示这一点,但我看不到在此处附加它的方法。

              这是代码:(使用 VS 2008 SP1 构建,针对 .net 3.5 - 我使用了 WPF 项目)。 WPF项目中有2个项目,主窗口(window1),以及我们正在测试的对象(DataObject) 窗口上有一个标签,它数据绑定到数据对象实例中的 Name 属性。如果将 Name 属性转换为字段(删除 getter/setter),数据绑定将停止工作。

              Window1.xaml:

              <Window x:Class="WpfDatabinding.Window1"
              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              Title="Window1" Height="300" Width="300">
              <Grid>
                  <Label Name ="Label1" Height="28" Margin="12,24,37,0" VerticalAlignment="Top" Content="{Binding Name}"></Label>
              </Grid>
              

              Window1.xaml.cs

              using System;
              using System.Windows;
              
              namespace WpfDatabinding
              {
                  /// <summary>
                  /// Interaction logic for Window1.xaml
                  /// </summary>
                  public partial class Window1 : Window
                  {
                      private DataObject ADataObject;
              
                      public Window1()
                      {
                          InitializeComponent();
                          this.ADataObject = new DataObject();
                          this.ADataObject.Name = "Hello!";
                          this.DataContext = this.ADataObject;
                      }
                  }
              }
              
              namespace WpfDatabinding
              {
                  /// <summary>
                  /// Interaction logic for Window1.xaml
                  /// </summary>
                  public partial class Window1 : Window
                  {
                      private DataObject ADataObject;
              
                      public Window1()
                      {
                          InitializeComponent();
                          this.ADataObject = new DataObject();
                          this.ADataObject.Name = "Hello!";
                          this.DataContext = this.ADataObject;
                      }
                  }
              }
              

              DataObject.cs:

              namespace WpfDatabinding
              {
                  public class DataObject
                  {
                      // convert this to a field, and databinding will stop working
                      public string Name
                      {
                          get;
                          set;
                      }
                  }
              }
              

              【讨论】:

                猜你喜欢
                • 2014-03-15
                • 1970-01-01
                • 2019-01-24
                • 2019-02-27
                • 1970-01-01
                • 2010-09-09
                • 2020-09-21
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多