我看到成员变量给定了一个私有修饰符,然后使用getter / setter方法来设置和获取变量的值(以标准化的名义)。
为什么不将变量公开给自己(除了像弹簧框架这样依赖于IOC的getter / setter等的情况)。它符合目的。
在C#中,我看到了getter / setter,其中包含成员变量的大小写。为什么不把变量公开呢?
答案 0 :(得分:8)
从第一张照片中获取稳定的API 。 Java专家认为,如果以后,您可能希望在设置/获取实例成员时有一些额外的逻辑,则不希望通过使用公共方法替换公共字段来破坏现有API 。这是Java的主要原因。
对于C#,由于二进制接口兼容性,因此使用公共属性而不是公共字段。有人在这里问a similar question,在SO。
所以,所有这些都是关于封装某些逻辑,同时仍保留接口以进行未来验证。
答案 1 :(得分:4)
即使在2003年,人们也知道getter and setter methods are evil。
答案 2 :(得分:4)
因为 interfaces 只允许指定方法,而不允许指定变量。接口是API的基石。
因此,要通过界面访问字段,您需要来获取getter和setter。
答案 3 :(得分:2)
您还提到了C#属性。这些实际上只是吸气剂/固定器,但使用更简洁的语法。
答案 4 :(得分:2)
这样做是为了您可以在发布之后更改公共API中的getter或setter实现。使用公共字段,您将无法检查有效性值。
答案 5 :(得分:2)
它是encapsulation的一部分:从实现(使用实例变量)抽象出类的接口(“getters”和“setters”)。虽然您可能决定通过直接访问实时变量今天来实现该行为,但您可能希望以不同的方式明天。假设你需要通过网络检索值而不是在本地存储它 - 如果你已经封装了行为,这是一个微不足道的变化。但是,如果其他对象依赖于对实例变量的直接访问,那么你就会陷入困境。
答案 6 :(得分:2)
Java中getter和setter的最重要用途是惹恼开发人员。第二个最重要的用途是用无用的噪声使代码混乱。此外,它会强制您为同一事物使用不同的名称,具体取决于您所在的位置(在课程内部或外部)。不要忘记添加的歧义(你是否在课堂上调用getter或者直接使用该字段?)接下来,它们用于允许访问私有数据,但这只是一个小的副作用;)
在其他编程语言中,编译器将为您生成它们(当然,除非您提供自己的实现)。例如,在Delphi中,您有read
和write
个字段修饰符(就像Java中的private
,static
或final
。定义你是否会为你生成一个getter或setter。
与德尔福人不同,Java人员希望一切都是明确的。 “如果它不在源头,它就不存在”。所以唯一的解决方案就是强迫人们手动编写所有的getter和setter。更糟糕的是,人们不得不为同一件事使用不同的名称。
答案 7 :(得分:2)
(如果您希望稍后更改实现,则需要getter和setter来验证您的代码的想法是YAGNI的一个明显例子。但这确实是不重要的。)
答案 8 :(得分:2)
最常见的原因是对封装的理解不足。当开发人员认为封装内容真的只是吸气剂和放大器时。建立者而不是封装行为。
获得getter / setter的正当理由是:
1)您正在创建一个通用的对象,例如JComponent。通过使用getter / setter而不是直接访问变量意味着您可以首先对所述变量进行一些预处理(例如验证它是否具有设置范围)或更改底层实现(从int切换到BigInteger)无需更改公共API)。
2)您的DI框架不支持ctor注入。通过只设置一个setter,你可以确保变量只设置一次。
3)(与#1联系)允许工具与您的对象进行交互。通过使用这样一个简单的约定,GUI工具可以轻松获得给定组件的所有设置。这方面的一个例子是NetBeans中的UI构建器。
¹非通用类型。使用不好的词我知道,请提出另一种选择。
答案 9 :(得分:2)
拥有一个setter可以
在有问题的情况下,如果简单地读取或写入该值,则不需要getter和setter。
答案 10 :(得分:1)
答案 11 :(得分:0)
有些Java框架需要它们(我认为是JavaBeans)。
- 编辑
有些海报试图说这是关于封装的。事实并非如此。
封装是关于隐藏对象的实现细节,并且只暴露相关的函数。
提供一个除了设置值之外什么都不做的get / set根本不会完成这个,并且它们的唯一原因是:
答案 12 :(得分:0)
如果存在约束或者进行一般有效性检查或在更改或其他事件上发布事件,则需要封装这些属性。基本用法是将属性隐藏在“外部世界”中。
答案 13 :(得分:0)
有几个原因:
进一步的代码支持:如果将来某个时候你需要在变量的每次访问/变异(获取/设置)之前执行一些操作,那么你将遇到更少的问题。 在C#构造中,如
public int Age { 得到 { return(int)(today() - m_BirthDate); } }
只是语法糖。
答案 14 :(得分:0)
属性理念是OOP(面向对象编程)的核心。但问题是Java不是在语言的核心(语法/ JVM)中引入它们,而是(可能几年之后...... Java的历史更好)作为惯例:一致的getter / setter对是 bean 中的属性,属性的概念在库中,而不在核心中。
这在少数库,框架中产生问题。单个getter是否为只读属性?就是那个问题。 I.e.in JPA实体如果你想实现经典方法(算法),像getCurrentTine()
这样的“get”前缀是@Transient禁用像属性有价值的解释的最佳标记。
换句话说,我非常喜欢C#10年后设计的更好的财产概念。 BTW C#属性也有getter / setter,但有时/部分隐藏,在低级调试时可见。免于提问“为什么会有吸气”等......
在Java世界中,阅读有关Groovy属性概念(隐藏的getter / setter的方式与C#不同)很有趣http://www.groovy-lang.org/objectorientation.html#_fields_and_properties
编辑:从现实生活中,每个java对象都有getClass()
方法,java.beans.BeanInfo
包中的工具将此报告为属性"class"
,但事实并非如此。完全意义上它不是财产(只读属性)。我想像C#这样的属性(内部隐藏名称为get_Something1)与“functional”GetSomething2()没有冲突