总是使用 get 和 set 方法来访问类自己的成员字段是否属于反模式?
在 Java 类中,使用 getter 和 setter 访问成员字段被认为是好还是坏做法?
例如哪个更好:
public Order {
private Agreement agreement;
public Agreement getAgreement() {
return agreement;
}
public void process() {
//should I use:
getAgreement().doSomething();
//Or:
agreement.doSomething();
}
}
一般来说,我认为由于 KISS 原则,直接访问该字段是最好的,而且有人可能会在以后重写 get 方法,从而产生不可预测的结果。
然而我的同事认为最好保留一个抽象层。 对此有共识吗?
In Java classes is it considered good or bad practice to access member fields with their getters and setters?
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.
However my colleagues argue that it is better to keep a layer of abstraction. Is there any consensus on this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
老实说,在我看来,这取决于你用它来做什么。 就我个人而言,当有疑问时,我总是将额外的抽象级别留在那里,以防万一我稍后需要在子类中重写它。 很多时候,我从重写类的痛苦中解脱出来,只是因为我留下了一个可供重写的 getter 或 setter。
另一件事是其他客户端/程序员可能需要以您尚未想到的方式使用您的类,例如,从数据库中提取协议类。 在这种情况下,当他们重写您的类时,您可以让他们(或者可能是未来的您)轻松修改数据的检索方式。
因此,除非您完全确定只有一种方法可以访问该字段,并且它是 100% 直接的,否则最好将值的检索和修改解耦,以便在将来的某个时候您可以避免重写困难。
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.
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.
这里的核心问题是直接字段访问不符合子类重写方法、AOP、动态代理等拦截的条件。 根据具体情况,这可能是好事也可能是坏事。 我想说,在内部使用 getter 和 setter 不是反模式或模式。 这是好事还是坏事取决于具体情况以及班级的设计。
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.
我认为类的公共接口代表了围绕状态的封装,因此甚至该类的其他工作也受益于该封装。
如果您已将字段包装在公共 get 方法中,那么您这样做是有原因的。 也许该方法中存在延迟加载字段或提供审计跟踪的逻辑。 无论该方法的原因是什么,您的类很可能也需要该逻辑。
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.
在我看来,有些人将这个问题解释为关于外部使用的 getter 和 setter; 我对 Pablojim 问题的解释是,它是在类中使用它们,而不是类直接访问其字段。 (这是私人的。)
从这个角度来看,我支持 Jherico 和 patros; 除非有某种原因不这样做,否则从类内部使用直接访问。
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.)
In that light, I'm with Jherico and patros; use direct access from within the class unless there's some reason not to.
在 Java 中保留一个抽象层是一件好事。
问题在于,所有直接访问成员变量而类没有注意到的代码不受类的控制。
因此,当您决定以一种方式编辑您的类时,例如,在部门中使用的一个成员永远不应该为 0,您必须能够确保该值仅以确保这一点的方式更改。 因此,您可以为此方法添加一个设置器并将成员更改为私有。 但现在您需要更改所有在没有 setter 的情况下访问成员的代码。
如果您知道要从类外部更改值,并且只有在不知道将变量设为私有的情况下才提供 setter,并且如果稍后需要访问,则可以提供 getter 或 setter。
如果其他对象中的某些方法始终对成员使用 get,然后执行一些计算,然后使用 get,则它会得到反模式。 这表明该成员应该位于另一个类中,或者该方法需要位于此类中。
拥有 getter 和 setter 而不考虑每个成员都会破坏封装,这不是一个好的设计选择。 有关更多内部信息,请阅读这篇文章
Keeping a layer of Abstraction is a good thing in 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.
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.
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 之外,我们还需要更改引用该变量的所有位置。 这是需要记住的事情。
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 和 setter 的用途。 通常,当我需要对进入类的数据进行健全性检查或格式化传出的数据时,我会使用它们。 在这方面,我确实使用 getter 和 setter 作为此类与可能需要访问其数据的其他类之间的接口层。
我倾向于编写内部代码,使其知道如何处理此类的私有数据,因此使用其自己的 getter 和 setter 访问它通常是不必要且不受欢迎的。
不过,这完全取决于您如何使用 getter 和 setter。
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.
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.
It all depends on how you use your getters and setters, though.
我的经验法则是,如果他们做的事情比仅仅设置或返回值更复杂,请使用 setter/getter。 否则,就不需要它,因为您可以修复由成员变量更改引起的任何问题。
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.
你是对的,为每个属性变量做所有额外的工作很烦人。 为什么该语言允许一些如此基本但没人做的事情? 然而,有非常令人信服的理由不允许直接访问属性。
我更喜欢埃菲尔的统一访问原则。 您永远不能分配给属性,并且属性和函数以相同的方式访问:
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:
我觉得这个问题需要具体情况具体分析。 在整个类代码中使用 getter 确实会使事情变得复杂,并且可能会使其速度稍微慢一些。 然而,它也使其更具可扩展性和可重用性。
如果我能预见到有人可能想用另一个吸气剂覆盖我的吸气剂,我通常会使用吸气剂。 如果它是非常基本和简单的东西,它永远不会有意义,我通常不使用吸气剂。
如果您编写代码来访问没有 getter 的变量,请考虑将 getter 函数设置为“final”。 这样,就没有人会尝试覆盖您的代码并抓狂地想知道为什么它不起作用。 (请注意,Spring 和 Hibernate 代理可能会使这成为一个坏主意。)
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.
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.
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 和 setter 会有什么危害。 最多,这是浪费时间(和打字),这使得它毫无意义,但不是反模式。
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.