Getter 和 setter在面向对象编程中强制执行封装的概念。
通过将对象的状态隐藏在外部世界之外,对象真正掌控自己,并且不能以非预期的方式进行更改。可以操作对象的唯一方法是通过公开的公共方法,例如 getter 和 setter。
拥有 getter 和 setter 有几个优点:
1. 允许将来更改而不修改使用修改后的类的代码。
使用 getter 和 setter 的一大优势是,一旦定义了公共方法,就会有一段时间需要更改底层实现(例如,找到需要修复的错误,使用不同的算法来提高性能等),通过让 getter 和 setter 成为操作对象的唯一方法,它将允许现有代码不会中断,并且即使在更改之后也可以按预期工作。
例如,假设有一个setValue
方法value
在对象中设置私有变量:
public void setValue(int value)
{
this.value = value;
}
但是随后,有一个新的要求需要跟踪value
更改的次数。使用 setter 后,更改就相当简单了:
public void setValue(int value)
{
this.value = value;
count++;
}
如果该value
字段是公开的,则没有简单的方法可以稍后返回并添加一个跟踪值更改次数的计数器。因此,拥有 getter 和 setter 是一种让类“面向未来”以应对以后可能发生的变化的方法。
2. 执行可以操纵对象的方法。
getter 和 setter 派上用场的另一种方式是强制执行对象可以被操纵的方式,因此,对象可以控制自己的状态。暴露对象的公共变量后,它很容易被破坏。
例如,一个ImmutableArray
对象包含一个int
名为 的数组myArray
。如果数组是一个公共字段,它就不会是不可变的:
ImmutableArray a = new ImmutableArray();
int[] b = a.myArray;
b[0] = 10; // Oops, the ImmutableArray a's contents have been changed.
要实现一个真正不可变的数组,应该为数组(getArray
方法)编写一个 getter,以便它返回其数组的副本:
public int[] getArray()
{
return myArray.clone();
}
即使发生以下情况:
ImmutableArray a = new ImmutableArray();
int[] b = a.getArray();
b[0] = 10; // No problem, only the copy of the array is affected.
ImmutableArray
确实是不可变的。公开对象的变量将允许以非预期的方式对其进行操作,但仅公开某些方式(getter 和 setter),可以以预期的方式操作对象。
我认为拥有 getter 和 setter 对于作为 API 一部分的类将被其他人使用更为重要,因为它允许保持 API 完整和不变,同时允许对底层实现进行更改。
说完 getter 和 setter 的所有优点,如果 getter 只是返回私有变量的值,而 setter 只是接受一个值并将其分配给私有变量,那么 getter 和 setter 似乎是无关紧要的,实际上是一个浪费。如果该类仅供应用程序内部使用而不会被其他人使用,那么广泛使用 getter 和 setter 可能不如编写公共 API 时那么重要。