getter和setter执行额外的逻辑

我有一个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的可能空值的事实):

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

困扰我的是将此逻辑添加到getter方法中,如果我更改方法名称或记录它应该被认为是足够的?

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

不幸的是,随着时间的推移,程序员越来越依赖于getter / setter只是底层属性的访问者/ mutator,趋势有点像官方POJO的引入,以识别只有getter和可能的对象塞特斯作为方法。

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

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

希望这可以帮助。

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

鉴于相关性是来自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; } } 

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

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

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

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

如果主要根据a和b计算相关性,则应删除setCorrelation()。 期。 应该在构造函数或getCorrelation()方法中计算相关性。 OOP的一个原则是对相关数据和逻辑进行分组,因此理想情况下,应该在您巧妙地命名为Correlation的类中完成相关性的计算。 如果计算极其复杂,可能在其他地方(例如DIP),但调用应该来自Correlation

如果不是从a和b计算相关性,我真的不理解这个类,所以“它取决于”。 如果a确实等于b,并且有人调用setCorrelation(0.0),那么合约是否会静静地忽略该调用并将相关性保留为1.0,或者抛出exception? 而且,如果我正在编写调用代码,那我就陷入了困境,因为我不知道如果我尝试setCorrelation(0.0)会发生什么,因为我不知道a和b是什么,或者每个地方我都知道打电话我被迫去if (getA().equals(getB()))等…或者去抓住Exception并做,呃,什么? 这违反了DRY,正是OOP说逻辑和数据应该在一个类中组合在一起的原因。