getter和setter执行额外的逻辑

时间:2011-10-31 14:46:22

标签: java pojo

我有一个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方法中,如果我更改方法名称或记录它应该被认为是足够的吗?

7 个答案:

答案 0 :(得分:14)

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

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

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

答案 1 :(得分:6)

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

希望这有帮助。

答案 2 :(得分:1)

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表示尚未设置相关性。

答案 3 :(得分:1)

鉴于相关性是来自a和b的某种方式/有时“衍生”的值(即,如果a等于b,则它是1,但是可以根据(a,b)以某种原始方式计算,一个好的选择可以如果vaule违反了对象的内部逻辑,则计算构造函数中的相关性并在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;
    }
}

遵循此方案,您还可以“生成”您的关联类。

答案 4 :(得分:0)

我会说使用像getValue()

这样的东西

答案 5 :(得分:0)

如果我使用你的课程,我希望getCorrelation()能够返回相关性。实际上,我可能会重新设计类以使用返回double的静态方法correlateElements(String a,String b)。

答案 6 :(得分:0)

在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说逻辑和数据应该在一个类中组合在一起的原因。