让我的吸气剂方法改变储值是不好的做法吗?


70

在我的班级中更改我的getter方法(例如版本2)是否是不好的做法?

版本1:

 public String getMyValue(){
     return this.myValue
 }

版本2:

 public String getMyValue(){

    if(this.myValue == null || this.myValue.isEmpty()){
       this.myValue = "N/A";
    }

    return this.myValue;
 }

5
恕我直言,如果在文档中清楚记录了这种副作用,那是可以的
jlordo 2012年

我更喜欢getter函数永远不会改变对象的值。您可以在其他功能中执行此检查,并在一个setter功能中设置其值。只是为了有一个清晰的代码。
Maroun 2012年

3
我认为这很糟糕,因为似乎您正在将演示文稿与数据模型混合在一起。当您的应用程序需要翻译成其他语言时会发生什么?
MTilsted

8
我找不到您的更改,但总的来说,我认为更改吸气剂是可以的。毕竟,getter是一种抽象,使我们能够更改内部行为而不会破坏其他代码。
Matsemann

2
问题标题不应该读成,Is it bad practice for a getter to change an object's member's value?因为这听起来像是您在问更改吸气剂的内部实现是否有害,我相信答案是否定的,可以更改它。
vikki

Answers:


117

我认为,如果您的getter方法更改了对象的内部状态,那实际上是一个不好的做法。

为了达到同样的,我建议刚回国"N/A"

  • 通常,此内部字段可能在其他不需要使用getter方法的地方(内部)使用。因此最后,对的调用foo.getMyValue()实际上可能会更改的行为foo

或者,可以在设置器中完成从null到的转换,即,如果传递了内部值,则可以将其设置为。"N/A""N/A"null


一般说明:
我只会添加状态,例如"N/A"某些依赖于您的代码的API或其他实例所期望的状态。如果不是这种情况,则应依靠编程语言中可用的标准空类型。


43
请注意:我认为在延迟加载的情况下,getter可以更改对象的内部状态,在这种情况下,您特别希望仅在调用getter时才加载数据。
Vincent Mimoun-Prat

5
足够公平,这是一个有效的用例。但是,OP描述的情况可能会导致可怕的副作用。
fgysin恢复Monica 2012年

4
没有什么比处理在getter上更改状态并在每次调试器的某些组件每次访问它时在调试时更改状态的Property更为烦人的了。
Chuu 2012年

6
我认为更改吸气剂中对象的内部状态没有任何问题。对象的内部状态是类作者的业务。作为该类的用户,只要外部接口保持一致,就不应该知道(或关心)内部正在发生的事情。因此,无论他是在setter中设置值还是在getter中惰性设置值,这都是完全有效的。重要的是,getter始终为空值或空值返回N / A。
劳伦特

1
同意@Laurent,这只是实例变量的延迟初始化,是相当普遍的做法。不知道是否要检查.isEmpty(),甚至不能"N/A"用作默认值(我可能更喜欢使用Null对象或异常,因为默认情况下的值/处理方式通常取决于调用方,而不仅取决于被调用对象)
Damien Pollet 2012年

38

我认为,除非您正在这样做lazy-loading(否则您不会这样做),则吸气剂不应更改该值。所以我会:

将更改放入设置器中

public void setMyValue(String value) {
    if(value == null || value.isEmpty()){
        this.myValue = "N/A";
    } else {
        this.myValue = value;
    }
}

或者,如果值设置不正确,则使getter返回默认值:

public String getMyValue() {
    if(this.myvalue == null || this.myvalue.isEmpty()){
        return "N/A";
    }    
    return this.myValue;
}

在延迟加载的情况下,我会说在getter中更改成员是可以的,您将执行以下操作:

public String getMyValue() {
    if (this.myvalue == null) {
        this.myvalue = loadMyValue();
    }    
    return this.myValue;
}

为什么要调用延迟加载方法get ...()?调用类似load ...()的方法似乎更合适,不是吗?
卢卡斯·霍普纳

因为getter会直接返回值,除非之前从未加载过该值(因此loadMyValue将对getter内部的调用)。调用getter loadMyValue将暗示(根据我)无论如何都将加载该值。
Vincent Mimoun-Prat

11

不,您在这里做两件事。获取和设置。


我实际上更喜欢接受的答案。它指出您可以返回值“ N / A”,而不是先更改类变量。
Mark W

10

是。这是一个坏习惯。

为什么?

设置值时(在构造函数或setter方法中),应进行验证,而不是在调用getter方法时进行验证。private validate*为此创建一个方法也是一个好主意。

private boolean validateThisValue(String a) {
     return this.myValue != null && !this.myValue.isEmpty();
}

public void setThisValue(String a) {
    if (validateThisValue(a)) {
        this.myValue = a;
    } 
    else {
        // do something else
        // in this example will be
        this.myValue = "N/A";
    }
}

并且,在getter方法中,永远不会更改对象的状态。我已经完成了一些项目,并且经常必须使用getterconst方法:“此方法不能更改内部状态”。

至少,如果您不想使事情复杂化,则在getter方法中,您应该返回 "N/A"而不是更改内部状态并将其设置myValue"N/A"


4
我不同意永不更改设置器中的值。使用getter / setter的全部目的是抽象内部和外部实现。 Person.setHeightInCentimeters(int value)Person.setHeightInMeters(double value)Person.setHeightInFeetAndInches(int feet, int inches)都应该共享一个内部表示,这意味着它们中的至少两个将存储输入值以外的内容。
Dan在Firelight的抚养下

啊。对不起这么多:(我类型不匹配,不会改变在吸气的东西不是制定者,你在我的代码看,我有二传手的改变内部状态我已经编辑我很抱歉这么多。。。
HQT

6

我通常定义一个特定的 getter

永远不要更改原始内容getter

 public String getMyValue(){
     return this.myValue
 }

并创建一个特定的getter

public String getMyValueFormatted(){

    if(this.myvalue == null || this.myvalue.isEmpty()){
       return "N/A";
    }else{
       return this.myValue;
    }
 }

您怎么知道什么时候打给谁?
Abhishek Mehta

第二种方法的目的是为了向用户显示。
罗德里戈

那么,第一个不应成为公众吗?
Abhishek Mehta

不,两个都是公开的。首先使用来获取原始价值。需要格式化值时,请使用第二个。很简单,您不需要复杂的getter/setter方法。
罗德里戈

1
对于正在调用该API的新开发人员而言,这会造成混乱。第一种方法:将第一个公共方法重命名为getMyValueOriginal,将第二个方法重命名为getMyValueFormatted。
Abhishek Mehta

5

我认为最好初始化this.myValue = "N/A"。以及随后的致电setMyValuethis.myValue根据您的业务状况进行修改。
getMyValue不应该以任何方式修改this.myValue。如果您需要返回某个值,则应返回该值(例如“ N / A”),而不要更改this.myValue。获取者不得修改成员的值。


4

我会更好地更改setter方法,因此,如果值是null或为空,则将N/A其分配给属性。因此,如果您在类内的其他方法中使用该属性(vgtoString())则会在其中获得预期的值。

或者,更改setter方法以在设置的值不正确时启动异常,因此程序员必须在设置值之前改善其处理。

除此之外,还可以。


4

除非并且直到您解释了为什么在getter方法中修改对象而不是在setter方法中修改对象的必要性,否则我确实认为这是一种不良做法
您是否出于某种原因无法做到这一点?您能详细说明一下吗?


4

做任何你喜欢的事。毕竟,getter和setter只是另一种公共方法。您可以使用其他任何名称。

但是,如果您使用诸如之类的框架Spring,则势必会使用这些标准名称,并且永远不要将自定义代码放入其中。


4

绝对可以,这是很糟糕的做法。

想象一下,您与第三方(远程,COM,...)在整个网络上进行通信,这将增加往返行程,进而影响应用程序性能。


4

设置器可以作为验证的一部分进行修改,但获取器应返回值,并由调用方完成验证。如果您确实进行验证,则应如何记录。


3

这实际上高度取决于您要使用get()方法执行的合同。根据按合同设计的约定,调用者必须确保满足前提条件(这意味着用setter方法进行验证通常实际上是不好的设计)和被调用者(我不知道这是否是正确的英语术语) (即被叫人)确保满足发布条件。

如果您定义合同以便不允许使用get()方法更改对象,则您正在破坏自己的合同。考虑实施类似的方法

public isValid() {
    return (this.myvalue == null || this.myvalue.isEmpty());
}

这种方法的优点是您不必检查get()的返回是否为“ N / A”或其他。也可以在调用set()以确认您没有在对象中插入非法值之前调用此方法。

如果要设置默认值,则应在初始化期间执行此操作。


3

吸气剂的状态变化应属悬赏。这意味着客户端代码必须注意其访问getter和setter的顺序,并且这样做必须了解实现。您应该能够以任何顺序调用getter并仍然得到相同的结果。当设置器根据对象的当前状态修改输入值时,会发生一个相关的问题。


1
究竟!如果您需要绳子,请告诉我。
Alexandre M

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.