是否总是使用get和set方法来访问类自己的成员字段? [重复]

时间:2021-12-12 22:46:18

This question already has an answer here:

这个问题在这里已有答案:

In Java classes is it considered good or bad practice to access member fields with their getters and setters?

在Java类中,使用getter和setter访问成员字段是不是很好或者不好?

e.g which is better:

例如哪个更好:

public Order {
    private Agreement agreement;

    public Agreement getAgreement() {
    return agreement;
    } 

    public void process() {
       //should I use:
       getAgreement().doSomething();
       //Or:
       agreement.doSomething();
    }
}

In general I think accessing the field directly is best due to the KISS principle and also someone may override the get method later with unpredictable results.

一般来说,我认为直接访问该字段最好是由于KISS原则,并且有人可能会在以后使用不可预测的结果覆盖get方法。

However my colleagues argue that it is better to keep a layer of abstraction. Is there any consensus on this?

然而,我的同事认为保留一层抽象更好。对此有何共识?

11 个解决方案

#1


The core issue here is that direct field access is ineligible for interception by subclass overridden methods, AOP, dynamic proxies and the like. This can be a good or bad thing depending on the case. I would say that using getters and setters internally is not an anti-pattern or a pattern. It is a good or bad thing depending on the situation, and the design of your class.

这里的核心问题是直接字段访问不适合通过子类重写方法,AOP,动态代理等进行拦截。根据具体情况,这可能是好事也可能是坏事。我会说在内部使用getter和setter不是反模式或模式。根据情况和班级设计,这是好事还是坏事。

#2


Honestly, in my opinion, it depends on what you're using it for. Personally, when in doubt, I always leave that extra level of abstraction in there just in case I need to override it later in a subclass. Many times have I been saved from the pain of rewriting a class just because I left a getter or a setter open to overriding.

老实说,在我看来,这取决于你使用它的原因。就个人而言,如果有疑问,我总是在那里留下额外的抽象级别,以防我以后需要在子类中覆盖它。很多时候,我只是因为我让一个吸气剂或者一个二传手打开而无法改写课程,从而避免了重写课程的痛苦。

Another thing is that other clients/programmers might need to use your class in a way that you haven't yet thought of, for example, pulling the Agreement class out of a database. In that case, when they override your class, you have made it painless for them (or potentially a future you) to modify how that data is retrieved.

另一件事是其他客户端/程序员可能需要以您尚未想到的方式使用您的类,例如,将Agreement类从数据库中拉出来。在这种情况下,当他们覆盖你的类时,你已经让他们(或者可能是你的未来)无法修改数据的检索方式。

So unless you're absolutely certain that there is only one way to access that field, and that it's 100% direct, it's probably best to decouple the retrieval and modification of values so that at some future point you can save yourself from rewrite hardship.

因此,除非您完全确定只有一种方法可以访问该字段,并且它是100%直接的,所以最好将值的检索和修改分离,以便在将来某一点上您可以避免重写困难。

#3


I think that the public interface of a class represents encapsulation around state and as such even the other workings of the class benefit from that encapsulation.

我认为类的公共接口表示围绕状态的封装,因此即使该类的其他工作也受益于该封装。

If you have wrapped a field in a public get method then there is a reason you have done so. Perhaps there is logic within that method to lazy-load the field, or provide an audit trail. Whatever the reason for the method, your class will most likely need that logic as well.

如果你在一个公共get方法中包装了一个字段,那么你就有这样做的原因。也许在该方法中存在惰性加载字段或提供审计跟踪的逻辑。无论该方法的原因是什么,您的班级也很可能也需要这种逻辑。

#4


It sounds to me like some people are interpreting this question as being about getters and setters that are used externally; my interpretation of Pablojim's question was that it's about using them within the class, as opposed to the class directly accessing its fields. (Which are private.)

听起来像是有些人将这个问题解释为关于外部使用的吸气剂和固定剂;我对Pablojim的问题的解释是,它是关于在类中使用它们,而不是直接访问其字段的类。 (这是私人的。)

In that light, I'm with Jherico and patros; use direct access from within the class unless there's some reason not to.

从那时起,我就和Jherico和patros在一起;除非有某些理由不这样做,否则从课堂内直接访问。

#5


Keeping a layer of Abstraction is a good thing in Java.

在Java中保持一层抽象是一件好事。

The problem is that all the code that directly accesses your member variables without the class noticing it isn't under the control of your class.

问题是所有直接访问你的成员变量但没有类注意到它的代码都不在你的类的控制之下。

So the moment you decide to edit your class in a way that one member that is used in a division as an example should never be 0 you have to be able to ensure that this value is only changed in a way that ensures this. So you would add a setter for this method and change the member to private. But now you need to change all the code that is accessing the member without the setter.
If you know you are changing the value from outside the class and only then provide a setter if you don't know make the variable private and if you need access later maybe provide a getter or a setter.

因此,当您决定以一个分区中使用的一个成员作为示例的方式编辑您的类时,您必须能够确保仅以确保这一点的方式更改此值。因此,您将为此方法添加一个setter,并将该成员更改为private。但是现在你需要在没有setter的情况下更改访问成员的所有代码。如果您知道您正在从类外部更改值,并且只有在您不知道将变量设为私有时才提供setter,如果您以后需要访问,则可以提供getter或setter。

It gets an Anti-Pattern if there are certain methods in other objects that are always using get for a member then performs some calculations and then uses get. This shows that either the member should be in the other class or that the method needs to be in this class.

如果其他对象中的某些方法总是使用get作为成员然后执行某些计算然后使用get,则它会获得反模式。这表明该成员应该在另一个类中,或者该方法需要在此类中。

Having a getter and a setter without thinking about it for every member breaks encapsulation and is not a good design choice. For mor insides read this article

拥有一个getter和一个setter而不考虑每个成员都会打破封装,这不是一个好的设计选择。对于mor insides,请阅读本文

#6


I'm now working on something that makes me in favor of the getters: we're now moving part of our properties into a "property bag", which means you cannot just reference the variable. So in addition of changing the getter, we need to change all the places that reference that variable. It's something to keep in mind.

我现在正致力于让我更喜欢吸气剂:我们现在将部分属性转移到“属性包”中,这意味着你不能只引用变量。因此,除了更改getter之外,我们还需要更改引用该变量的所有位置。这是要记住的事情。

#7


It depends on what you use your getters and setters for. Generally I use them when I need to sanity check data coming into a class or format data going out. In that respect, I really use getters and setters as an interface layer between this class and other classes that might need access to its data.

这取决于你使用getter和setter的用途。一般来说,当我需要理智地检查进入类中的数据或格式化数据时,我会使用它们。在这方面,我真的使用getter和setter作为此类与可能需要访问其数据的其他类之间的接口层。

I tend to write my internal code such that it knows how to handle data private to this class, so accessing it with its own getters and setters is generally unnecessary and undesired.

我倾向于编写我的内部代码,以便它知道如何处理这个类的私有数据,因此通过自己的getter和setter访问它通常是不必要的和不受欢迎的。

It all depends on how you use your getters and setters, though.

这完全取决于你如何使用你的getter和setter。

#8


My rule of thumb is that if they do anything more complex than just set or return the value, use the setters/getters. Otherwise, it's not needed since you can fix any problems caused by changes to the member variables.

我的经验法则是,如果他们做的事情比设置或返回值更复杂,请使用setters / getters。否则,不需要它,因为您可以修复由成员变量更改引起的任何问题。

#9


You're right in that it's annoying to do all that extra work for every attribute variable. Why does the language allow something so basic that no one does? There are very compelling reasons for not allowing direct attribute access, however.

你是对的,为每个属性变量做额外的工作是很烦人的。为什么语言允许一些基本没有人做的事情?但是,不允许直接属性访问有非常令人信服的理由。

I prefer Eiffel's Unified Access Principle. You can never assign to an attribute, and attributes and functions are accessed in the same way:

我更喜欢埃菲尔的统一访问原则。您永远不能分配属性,并且以相同的方式访问属性和函数:

class EXAMPLE
feature
  variable: INTEGER
  variable_function: INTEGER
    do
      result := 4
    end
  variable_two: INTEGER assign variable_assign
  variable_assign (in: INTEGER)
    do
      variable_two := in
    end  
end

feature
test
local
  test: EXAMPLE
  value: INTEGER
do
  create test
  value := test.variable  -- Valid
  value := test.variable_function  -- Valid and same even though it's a function
  test.variable := value -- Invalid
  test.variable_two := value -- Valid, an explicit setter is defined
end

#10


I think this is something that needs to be considered on a case by case basis. Using a getter throughout your class code does complicate it, and probably makes it slightly slower. However, it also makes it more extensible and reusable.

我认为这是需要根据具体情况考虑的事情。在整个类代码中使用getter会使它复杂化,并且可能会使它稍慢。但是,它也使它更具可扩展性和可重用性。

What I've usually done is use the getter if I can forsee any reason someone might want to override my getter with another one. If it's something so basic and simple that it would never make sense, I generally don't use getters.

我通常做的是使用吸气剂,如果我能预见到任何人可能想要用另一个覆盖我的吸气剂。如果它是如此基本和简单的东西,它永远不会有意义,我通常不使用getter。

If you write your code to access the variables without the getter, consider making the getter function "final". That way, no one will try to override your code and tear his hair out wondering why it's not working. (Note that Spring and Hibernate proxies might make this a bad idea.)

如果您编写代码以在没有getter的情况下访问变量,请考虑将getter函数设置为“final”。这样,没有人会试图覆盖你的代码并撕掉他的头发,想知道为什么它不起作用。 (请注意,Spring和Hibernate代理可能会让这个想法变坏。)

#11


In order for it to be an anti-pattern, it'd have to be decidedly harmful. I don't see how there can possibly be any harm in defining getters and setters. At most, it is a waste of time (and typing), which makes it pointless, but not an antipattern.

为了使它成为一种反模式,它必须具有明显的危害性。我没有看到定义getter和setter可能有什么坏处。最多是浪费时间(和打字),这使得它毫无意义,但不是反模式。

#1


The core issue here is that direct field access is ineligible for interception by subclass overridden methods, AOP, dynamic proxies and the like. This can be a good or bad thing depending on the case. I would say that using getters and setters internally is not an anti-pattern or a pattern. It is a good or bad thing depending on the situation, and the design of your class.

这里的核心问题是直接字段访问不适合通过子类重写方法,AOP,动态代理等进行拦截。根据具体情况,这可能是好事也可能是坏事。我会说在内部使用getter和setter不是反模式或模式。根据情况和班级设计,这是好事还是坏事。

#2


Honestly, in my opinion, it depends on what you're using it for. Personally, when in doubt, I always leave that extra level of abstraction in there just in case I need to override it later in a subclass. Many times have I been saved from the pain of rewriting a class just because I left a getter or a setter open to overriding.

老实说,在我看来,这取决于你使用它的原因。就个人而言,如果有疑问,我总是在那里留下额外的抽象级别,以防我以后需要在子类中覆盖它。很多时候,我只是因为我让一个吸气剂或者一个二传手打开而无法改写课程,从而避免了重写课程的痛苦。

Another thing is that other clients/programmers might need to use your class in a way that you haven't yet thought of, for example, pulling the Agreement class out of a database. In that case, when they override your class, you have made it painless for them (or potentially a future you) to modify how that data is retrieved.

另一件事是其他客户端/程序员可能需要以您尚未想到的方式使用您的类,例如,将Agreement类从数据库中拉出来。在这种情况下,当他们覆盖你的类时,你已经让他们(或者可能是你的未来)无法修改数据的检索方式。

So unless you're absolutely certain that there is only one way to access that field, and that it's 100% direct, it's probably best to decouple the retrieval and modification of values so that at some future point you can save yourself from rewrite hardship.

因此,除非您完全确定只有一种方法可以访问该字段,并且它是100%直接的,所以最好将值的检索和修改分离,以便在将来某一点上您可以避免重写困难。

#3


I think that the public interface of a class represents encapsulation around state and as such even the other workings of the class benefit from that encapsulation.

我认为类的公共接口表示围绕状态的封装,因此即使该类的其他工作也受益于该封装。

If you have wrapped a field in a public get method then there is a reason you have done so. Perhaps there is logic within that method to lazy-load the field, or provide an audit trail. Whatever the reason for the method, your class will most likely need that logic as well.

如果你在一个公共get方法中包装了一个字段,那么你就有这样做的原因。也许在该方法中存在惰性加载字段或提供审计跟踪的逻辑。无论该方法的原因是什么,您的班级也很可能也需要这种逻辑。

#4


It sounds to me like some people are interpreting this question as being about getters and setters that are used externally; my interpretation of Pablojim's question was that it's about using them within the class, as opposed to the class directly accessing its fields. (Which are private.)

听起来像是有些人将这个问题解释为关于外部使用的吸气剂和固定剂;我对Pablojim的问题的解释是,它是关于在类中使用它们,而不是直接访问其字段的类。 (这是私人的。)

In that light, I'm with Jherico and patros; use direct access from within the class unless there's some reason not to.

从那时起,我就和Jherico和patros在一起;除非有某些理由不这样做,否则从课堂内直接访问。

#5


Keeping a layer of Abstraction is a good thing in Java.

在Java中保持一层抽象是一件好事。

The problem is that all the code that directly accesses your member variables without the class noticing it isn't under the control of your class.

问题是所有直接访问你的成员变量但没有类注意到它的代码都不在你的类的控制之下。

So the moment you decide to edit your class in a way that one member that is used in a division as an example should never be 0 you have to be able to ensure that this value is only changed in a way that ensures this. So you would add a setter for this method and change the member to private. But now you need to change all the code that is accessing the member without the setter.
If you know you are changing the value from outside the class and only then provide a setter if you don't know make the variable private and if you need access later maybe provide a getter or a setter.

因此,当您决定以一个分区中使用的一个成员作为示例的方式编辑您的类时,您必须能够确保仅以确保这一点的方式更改此值。因此,您将为此方法添加一个setter,并将该成员更改为private。但是现在你需要在没有setter的情况下更改访问成员的所有代码。如果您知道您正在从类外部更改值,并且只有在您不知道将变量设为私有时才提供setter,如果您以后需要访问,则可以提供getter或setter。

It gets an Anti-Pattern if there are certain methods in other objects that are always using get for a member then performs some calculations and then uses get. This shows that either the member should be in the other class or that the method needs to be in this class.

如果其他对象中的某些方法总是使用get作为成员然后执行某些计算然后使用get,则它会获得反模式。这表明该成员应该在另一个类中,或者该方法需要在此类中。

Having a getter and a setter without thinking about it for every member breaks encapsulation and is not a good design choice. For mor insides read this article

拥有一个getter和一个setter而不考虑每个成员都会打破封装,这不是一个好的设计选择。对于mor insides,请阅读本文

#6


I'm now working on something that makes me in favor of the getters: we're now moving part of our properties into a "property bag", which means you cannot just reference the variable. So in addition of changing the getter, we need to change all the places that reference that variable. It's something to keep in mind.

我现在正致力于让我更喜欢吸气剂:我们现在将部分属性转移到“属性包”中,这意味着你不能只引用变量。因此,除了更改getter之外,我们还需要更改引用该变量的所有位置。这是要记住的事情。

#7


It depends on what you use your getters and setters for. Generally I use them when I need to sanity check data coming into a class or format data going out. In that respect, I really use getters and setters as an interface layer between this class and other classes that might need access to its data.

这取决于你使用getter和setter的用途。一般来说,当我需要理智地检查进入类中的数据或格式化数据时,我会使用它们。在这方面,我真的使用getter和setter作为此类与可能需要访问其数据的其他类之间的接口层。

I tend to write my internal code such that it knows how to handle data private to this class, so accessing it with its own getters and setters is generally unnecessary and undesired.

我倾向于编写我的内部代码,以便它知道如何处理这个类的私有数据,因此通过自己的getter和setter访问它通常是不必要的和不受欢迎的。

It all depends on how you use your getters and setters, though.

这完全取决于你如何使用你的getter和setter。

#8


My rule of thumb is that if they do anything more complex than just set or return the value, use the setters/getters. Otherwise, it's not needed since you can fix any problems caused by changes to the member variables.

我的经验法则是,如果他们做的事情比设置或返回值更复杂,请使用setters / getters。否则,不需要它,因为您可以修复由成员变量更改引起的任何问题。

#9


You're right in that it's annoying to do all that extra work for every attribute variable. Why does the language allow something so basic that no one does? There are very compelling reasons for not allowing direct attribute access, however.

你是对的,为每个属性变量做额外的工作是很烦人的。为什么语言允许一些基本没有人做的事情?但是,不允许直接属性访问有非常令人信服的理由。

I prefer Eiffel's Unified Access Principle. You can never assign to an attribute, and attributes and functions are accessed in the same way:

我更喜欢埃菲尔的统一访问原则。您永远不能分配属性,并且以相同的方式访问属性和函数:

class EXAMPLE
feature
  variable: INTEGER
  variable_function: INTEGER
    do
      result := 4
    end
  variable_two: INTEGER assign variable_assign
  variable_assign (in: INTEGER)
    do
      variable_two := in
    end  
end

feature
test
local
  test: EXAMPLE
  value: INTEGER
do
  create test
  value := test.variable  -- Valid
  value := test.variable_function  -- Valid and same even though it's a function
  test.variable := value -- Invalid
  test.variable_two := value -- Valid, an explicit setter is defined
end

#10


I think this is something that needs to be considered on a case by case basis. Using a getter throughout your class code does complicate it, and probably makes it slightly slower. However, it also makes it more extensible and reusable.

我认为这是需要根据具体情况考虑的事情。在整个类代码中使用getter会使它复杂化,并且可能会使它稍慢。但是,它也使它更具可扩展性和可重用性。

What I've usually done is use the getter if I can forsee any reason someone might want to override my getter with another one. If it's something so basic and simple that it would never make sense, I generally don't use getters.

我通常做的是使用吸气剂,如果我能预见到任何人可能想要用另一个覆盖我的吸气剂。如果它是如此基本和简单的东西,它永远不会有意义,我通常不使用getter。

If you write your code to access the variables without the getter, consider making the getter function "final". That way, no one will try to override your code and tear his hair out wondering why it's not working. (Note that Spring and Hibernate proxies might make this a bad idea.)

如果您编写代码以在没有getter的情况下访问变量,请考虑将getter函数设置为“final”。这样,没有人会试图覆盖你的代码并撕掉他的头发,想知道为什么它不起作用。 (请注意,Spring和Hibernate代理可能会让这个想法变坏。)

#11


In order for it to be an anti-pattern, it'd have to be decidedly harmful. I don't see how there can possibly be any harm in defining getters and setters. At most, it is a waste of time (and typing), which makes it pointless, but not an antipattern.

为了使它成为一种反模式,它必须具有明显的危害性。我没有看到定义getter和setter可能有什么坏处。最多是浪费时间(和打字),这使得它毫无意义,但不是反模式。