繁体   English   中英

类构造函数中的字段初始化:直接还是通过“ setter”?

[英]Field initialization in class constructors: direct or through “setter”?

经过一段时间使用C ++和C#后,我正在研究Java项目,并且对构造函数中字段初始化的最佳实践有疑问。 基本上,假设我有一个简单的Point类。 在C ++中,构造函数中的字段初始化如下所示:

class Point {
public:
    // Default constructor
    Point(double x, double y) : x(x), y(Y) { }

protected:
   // Coordinates
   double x, y;
};

在C#中...

class Point {
    // Coordinates, with automatic properties
    public double X { get; protected set; }
    public double Y { get; protected set; }

    // Default constructor
    Point(double x, double y) {
        X = x;
        Y = y;
    }    
}

在Java中,最佳做法建议为必须从外部访问的字段定义getters / setter方法。 但是建议也从类内部使用它们吗? 怀疑来自这样一个事实:即使我从类代码内部进行读/写操作,Eclipse对于将具有getter / setter的this.field = field将类代码中的每个this.field = field转换为setField(field)似乎也很满意。不需要使用类接口)。

基本上,每次访问都会添加一个函数调用。 现在,除了设置字段涉及其他一些操作(例如,验证,处理等)的情况之外,还有其他意义吗? 常识表明,使用getters / setters类似于使用C#属性,但在这里我特别质疑C#的自动属性 ,该属性仅涉及基本访问而没有任何处理。 所以问题是:在类代码内部调用getters / setter方法有什么好处,而无需任何其他处理?

谢谢
通努兹

Getters Setters封装了东西。 今天没有什么要处理的,但是明天您可能需要处理一些事情。 因此最好使用Getters Setters。

对于默认值初始化,可以使用构造函数。\\,但是如果在设置获取时进行一些处理,请使用Getters Setters。

最佳做法是使用

  • 构造器/初始化器块,用于将成员字段初始化为其值。
  • 直接从类访问字段中
  • 从外部使用吸气剂/吸气剂

另请参阅

我也希望直接访问。 但是,对于非平凡的get / setter,如果内部结构也需要非平凡的语义,则可能要使用它们。

如果您事先不知道get / setter将是非常规的,那么您也可能事先不知道内部结构是否也应该执行其他工作,因此过早的封装并没有它的用​​处可能会出现。

我的Eclipse(Helios)安装未执行此转换,因此我假定您可以将其关闭。

如果您要对要设置的值进行一些验证,格式化或处理,则建议使用setter。

假设您需要类Foo始终需要一个非空的bar值,当不使用setter时,每次设置该值时都需要重写验证代码:

public class Foo {

   private String bar;

   public Foo(String aValue) {

      if(aValue==null || aValue.equals("")) {
          throw new IllegalArgumentException("Duh");
      }

      bar=aValue;

   }

   public void setBar(String aValue) {

      if(aValue==null || aValue.equals("")) {
          throw new IllegalArgumentException("Duh");
      }

      bar=aValue;

   }
}

使用setter,您可以重用代码,并允许仅在一点上实现更多逻辑:

public class Foo {

   private String bar;

   public Foo(String aValue) {

      setBar(aValue);

   }

   public void setBar(String aValue) {

      if(aValue==null || aValue.equals("")) {
          throw new IllegalArgumentException("Empty values not allowed");
      }

      if(aValue.length()>24) {
           throw new IllegalArgumentException("Too long");
      }
      bar=aValue;

   }

}

正如我所教过的,在构造函数中不必使用getter和setter,而只会创建额外的方法调用来减慢程序速度。 我不确定这有多重要,因为此类方法调用通常在编译时内联。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM