我已阅读Java
上的书籍,并说最好为x
和y
等变量创建setter和getter。例如:
public int getX(){
return x;
}
public void setX(int x){
this.x = x;
}
但与此有什么不同
...(shape.x)... // basically getX()
和
shape.x = 90; // basically setX()
如果主持人和吸气者更好,你能解释一下会出现什么样的实际问题吗?
答案 0 :(得分:81)
多种原因:
如果您允许像
这样的字段访问shape.x = 90
然后您将来无法添加任何逻辑来验证数据。
如果x不能小于100你就不能这样做,但是如果你有像
这样的设定者public void setShapeValue(int shapeValue){
if(shapeValue < 100){
//do something here like throw exception.
}
}
虽然对于像
这样的常数public final String SOMETHING = "SOMETHING";
您将允许字段访问,因为它们无法更改,例如变量,您将使用getter,setter放置它们。
虽然在这种情况下你必须小心getter方法,以确保你不提供对象的引用(如果你的类有对象作为实例)。
我们可以使用getter和setter在任何包中使用私有变量。
答案 1 :(得分:10)
使用getter和setter函数可以实现约束和封装。可以说x是半径。 shape.x = -10没有多大意义。此外,如果有人试图设置非法值,您可以打印错误,设置默认值或什么都不做。
优良作法是将成员变量设为私有,以便使用它们的程序不能直接修改它们。
答案 2 :(得分:6)
很多人都提到封装实现的细节,对我来说这是在类中使用getter和setter的最大原因。有了这个,您还可以获得许多其他好处,包括能够随心所欲地抛弃和替换实现,而无需触及使用您的类的每一段代码。在一个小项目中,这不是一个很大的好处,但如果您的代码最终成为一个使用良好的(内部或公共)库,它可以是一个巨大的好处。
一个具体的例子:数学中的复数。有些语言将它们作为语言或框架功能,而其他语言则没有。我将在这里使用一个可变类作为例子,但它可以很容易地变成不可变的。
复数可以写在a + bi
表单上,包含实部和虚部,非常适合[gs]etRealPart
和[gs]etImaginaryPart
。
但是,在某些情况下,更容易推理极地形式re^(iθ)
上的复数,给出[gs]etRadius
(r)和[gs]etAngle
(θ)。
您还可以公开[gs]etComplexNumber(realPart, imaginaryPart)
和[gs]etComplexNumber(radius, angle)
等方法。根据参数类型,这些可能需要也可能不需要不同的名称,但是类的消费者可以根据需要使用它们。
这两种形式是可以互换的;您可以相当容易地从一个转换为另一个,因此类用于内部存储的形式与该类的消费者无关。但是,消费者可以使用任何一种形式如果您选择表单a + bi进行内部表示,而使用字段而不是getter和setter 进行公开,那么您不仅要强制类使用者使用该表单,您以后也无法轻易更改注意并用re ^(iθ)替换内部表示,因为事实证明在您的特定场景中更容易实现。你已经坚持使用你定义的公共API,它要求使用特定的字段名称来公开实部和虚部。
答案 3 :(得分:5)
以下示例
可以理解使用getter和setter的另一个好理由public class TestGetterSetter{
private String name ;
public void setName(String name){
this.name = name ;
}
public String getName(String name){
return this.name ;
}
}
getter和setter的意思是只有它们才能被用来访问它们正在获取或设置的私有变量。通过这种方式,您可以提供封装,以后可以更轻松地重构或修改代码。
想象一下,您使用名称而不是其getter。然后,如果你想添加类似默认的东西(比如默认名称是'Guest',如果它之前没有设置),那么你将不得不修改getter和sayName函数。
public class TestGetterSetter{
private String name ;
public void setName(String name){
this.name = name ;
}
public String getName(String name){
if (this.name == null ){
setName("Guest");
}
return this.name ;
}
}
不要求getter和setter以get和set开头 - 它们只是普通的成员函数。然而,这是一个惯例。 (特别是如果你使用Java Bean)
答案 4 :(得分:4)
我能想到的getter和setter的最佳理由之一就是类API的持久性。在像python这样的语言中,您可以按名称访问成员,并在以后将它们切换到方法。因为一旦你访问了一个属性,函数的行为与java中的成员不同。限制其范围后来打破了客户端。
通过提供getter和setter,程序员可以灵活地自由修改成员和行为,只要遵守公共API描述的合同即可。
答案 5 :(得分:3)
假设,假设您找到了一个能够更好地完成您在自己的课程中所做的工作的图书馆(YourClass)。此时要做的自然事情是使YourClass成为该库的包装器接口。它仍然有一个“X”的概念,您的客户端代码需要获取或设置。当然,此时你几乎必须编写访问函数。
如果您忽略使用访问器功能并让您的客户端代码直接访问YourClass.x,您现在必须重写所有曾触及YourClass.x的客户端代码。但是如果你从一开始就使用YourClass.getX()和YourClass.setX(),你只需要重写YourClass。
编程(尤其是面向对象编程)的一个关键概念是隐藏实现细节,以便它们不会被其他类或模块中的代码直接使用。这样,如果您更改了实现细节(如上例所示),则客户端代码不知道差异,也不必修改。对于您的所有客户端代码都知道,“x”可能是一个变量,或者它可能是一个即时计算的值。
这是过于简单化的,并未涵盖隐藏实现有益的所有场景,但这是最明显的例子。隐藏实现细节的概念现在与OOP紧密相关,但您可以在OOP被设想之前的数十年内找到它的讨论。它可以追溯到软件开发的核心概念之一,即解决一个大问题,并将其划分为可以轻松解决的小型定义明确的问题。访问器功能有助于保持小型子任务的分离和明确定义:您的课程对彼此内部的了解越少越好。
答案 6 :(得分:3)
最初,创建getter / setter模式是为了通过encapsulating
class
来自其外部interface
的内部来促进良好的面向对象设计。
这是您问题的最佳答案Why use getters and setters?
答案 7 :(得分:1)
有很多原因。这里只是几个。
答案 8 :(得分:1)
在得到答案之前,我们必须先了解一些事情......! “的的JavaBeans 强>”。
JavaBeans是具有属性的java类。出于我们的目的,将属性视为私有实例变量。因为它们是私有的,所以它们是唯一可以被访问的方式
来自课堂外的是通过课堂上的“方法”
更改属性值的方法称为 setter方法,检索属性值的方法称为 getter methods 。
答案 9 :(得分:0)
我想说,getter / setter和公众成员都不是良好的面向对象设计。它们都通过将对象数据暴露给可能不应该首先访问对象属性的世界来打破OOP封装。
答案 10 :(得分:0)
这是通过应用OOP的encapsulation原则来完成的。
用于限制对某些对象组件的访问的语言机制。
这意味着,您必须定义类的属性和方法的可见性。有三种常见的可见性:
当您声明私有/受保护属性时,建议您创建方法以获取值(get)并更改值(set)。可见性的一个示例是[ArrayList][2]
类:它具有size
属性以了解内部数组的实际大小。只有类必须更改其值,因此代码类似于
public class ArrayList<E> {
private int size;
private Object[] array;
public getSize() {
return this.size;
}
public void add(E element) {
//logic to add the element in the array...
this.size++;
}
}
在这个例子中,你可以看到size值只能在类方法中改变,你可以通过在代码中调用它来获得实际大小(不要改变它):
public void someMethod() {
List<String> ls = new ArrayList<String>();
//adding values
ls.add("Hello");
ls.add("World");
for(int i = 0; i < ls.size(); i++) {
System.out.println(ls.get(i));
}
}
答案 11 :(得分:0)
Getters和setter通过仅通过其公共方法访问它们来封装类的字段,并将值保持为私有。这被认为是一个很好的OO原则。
当然,如果它只是设置或返回一个值,它通常看起来像冗余代码。但是,setter还允许您进行输入验证或清理。在一个地方拥有它可以提高对象的数据完整性,
答案 12 :(得分:0)
因为我们使用的是面向对象的编程语言。 这里我们使用数据隐藏和封装。 该变量不应该直接从外部世界访问(用于实现数据隐藏),因此我们将私有创建
<强> shape.x 强>
不正确。 Getter和setter方法用于获取和设置x的值,这是实现封装的方法。