【问题标题】:getters and setters performing additional logic执行附加逻辑的 getter 和 setter
【发布时间】:2011-10-31 14:46:22
【问题描述】:

我有一个 Java 类,它表示两个元素之间的相关性(典型的 POJO):

public class Correlation {

    private final String a;
    private final String b;

    private double correlation;

    public Correlation(String a, String b) {
        this.a = a;
        this.b = b;
    }

    public double getCorrelation() {
        return correlation;
    }

    public void setCorrelation(double correlation) {
        this.correlation = correlation;
    }

}

要遵循正确的相关逻辑,如果 a 等于 b,则相关值应始终为 1。 我可以添加改变 getter 方法的逻辑(忽略 a 可能的 null 值的事实):

public double getCorrelation() {
    if (a.equals(b)) {
        return 1D;
    } else {
        return correlation;
    }
}

困扰我的是将这个逻辑添加到 getter 方法中,我应该更改方法名称还是记录它应该足够考虑?

【问题讨论】:

    标签: java pojo


    【解决方案1】:

    早在早期,Java getter/setter 对就被用来识别 beans 的 properties,目的是为了能够定义通过计算实现的概念属性而不是一个普通的成员变量。

    不幸的是,随着时间的流逝,程序员越来越依赖 getter/setter 作为底层属性的访问器/修改器,这种趋势在引入术语 POJO 识别只有 getter 和可能的 setter 作为方法的对象。

    另一方面,将执行计算的对象与仅携带数据的对象区分开来是一件好事。我想您应该决定要实现哪种类型的类。在你的位置,我可能会将相关性作为一个额外的构造函数参数并在那里检查它的有效性,而不是在你的 getter 中。您的Correlation 不能是计算对象,因为它没有足够的信息来执行任何计算。

    【讨论】:

    • +1;这就是全部真相!区分真实对象和哑数据传输对象很重要。
    • 我同意,除了最后一句话。我认为 Correlation 可以是一个计算对象,因为它(至少)可以在 a 等于 b 时计算相关性。
    • @Jala:当 a 和 b 相等且未定义时,相关性不是 1:一件事是检查参数,另一件事是计算所述参数的函数。
    • 即使在另一个类上定义了逻辑,你会在setter方法上添加值约束吗?
    • 再想一想,可能没有。该逻辑属于实际计算相关性的地方,并且该测试既非常局部又可能是多余的。另一方面,如果您必须拥有它,那是放置它的最佳位置;-)
    【解决方案2】:

    getter 和 setter 中的副作用通常不是一个好主意,因为它通常不是预期的,并且可能导致棘手的错误。我建议创建一个“correlate()”方法或其他在这种情况下不是专门为 getter 的方法。

    希望这会有所帮助。

    【讨论】:

    • 我没有看到他的第二个吸气剂有副作用。一个例外是,第一个 getter 可能会给出舍入错误。但这会使第二个 getter 更可取。
    • 同意。一般来说,最好的做法是让一种方法只在可能的情况下做一件事,并不惜一切代价避免副作用。将其视为应用于方法级别的单一职责原则。
    • 我同意将逻辑放在 getter/setter 中通常不是一个好主意,但有时您可能需要一些副作用 - 例如。用户对象可以在 setter/getter 中加密/解密密码
    • @aishwarya 同意好的观点,为了澄清我的回答,在 setter/getter 中执行的副作用或操作应该配对,以使用你的例子......如果你在 set 上加密值,你会获取时解密。
    【解决方案3】:

    在setCorrelation(...) 期间强制执行该值更有意义。例如,

    public void setCorrelation(double correlation) {
      if (a.equals(b)) {
        if (Math.abs(correlation - 1D) > EPSILON) {
          throw new InconsistentException(...);
        }
        this.correlation = 1D;
      } else {
        this.correlation= correlation;
      }
    }
    

    我还会考虑将相关属性设为可为空,其中 null 表示尚未设置相关性。

    【讨论】:

      【解决方案4】:

      鉴于相关性是从 a 和 b 以某种方式/有时“派生”的值(即,如果 a 等于 b,则它是 1,但它可能会根据 (a,b) 以某种原始方式计算,一个好的选择可以如果值违反了对象的内部逻辑,则在构造函数中计算相关性并在 setCorrelation 中抛出 IllegalArgumentException:

      public class Correlation {
      
          private final String a;
          private final String b;
      
          private double correlation;
      
          public Correlation(String a, String b) {
              this.a = a;
              this.b = b;
              calculateCorrelation();
          }
      
          protected calculateCorrelation() { 
              // open to more complex correlation calculations depending on the input,
              // overriding by subclasses, etc.
              if (a.equals(b)) {
                  this.correlation = 1D;
              } else {
                  this.correlation = 0;
              }
          }
      
          public double getCorrelation() {
              return correlation;
          }
      
          public void setCorrelation(double correlation) throws IllegalArgumentException {
              if (a.equals(b) && correlation != 1D) {
                  throw new IllegalArgumentException("Correlation must be 1 if a equals b");
              }
      
              this.correlation = correlation;
          }
      }
      

      按照这个方案,您还可以“生成”您的 Correlation 类。

      【讨论】:

      • 这是一个很好的方法,但是“a.equals(b) then 1”的逻辑在课堂上重复了两次。
      【解决方案5】:

      我会说使用 getValue() 之类的东西

      【讨论】:

      • 最后是名字的'get'部分让我很生气。
      【解决方案6】:

      如果我使用您的课程,我希望 getCorrelation() 返回相关性。事实上,我可能会重新设计该类,使其具有返回双精度的静态方法 correlateElements(String a, String b)。

      【讨论】:

        【解决方案7】:

        在a != b 的情况下,如何计算相关性?

        如果主要从 a 和 b 计算相关性,则应删除 setCorrelation()。时期。应在构造函数或 getCorrelation() 方法中计算相关性。 OOP 的一个原则是将相关数据和逻辑分组,因此理想情况下应该在你巧妙地命名为Correlation 的类中进行相关性的计算。如果计算非常复杂,可能在其他地方(例如 DIP),但应从Correlation 拨打电话。

        如果不是从 a 和 b 计算相关性,我真的不明白这个类,所以“它取决于”。如果 a 等于 b,并且有人调用 setCorrelation(0.0),那么合约是悄悄地忽略调用并将相关性保持在 1.0,还是抛出异常?而且,如果我正在编写调用代码,我会陷入困境,因为我不知道如果我尝试 setCorrelation(0.0) 会发生什么,因为我不知道 a 和 b 是什么,或者我在任何地方打个电话,我不得不去if (getA().equals(getB())) 等等……或者赶上异常然后做,呃,什么???这违反了 DRY,这正是 OOP 说逻辑和数据应该在一个类中组合在一起的原因。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-10-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-10-17
          相关资源
          最近更新 更多