为什么要使用getter和setter/访问器?
技术背景
在面向对象编程中,类的字段可以直接暴露给外部访问,也可以通过 getter 和 setter 方法来访问。直接暴露字段虽然简单,但缺乏封装性,不利于代码的维护和扩展。而 getter 和 setter 方法则提供了一种更灵活、更安全的方式来访问和修改类的字段。
实现步骤
1. 定义私有字段
为了实现封装,通常将类的字段定义为私有(private),这样外部代码就无法直接访问这些字段。
1 2 3 4 5
| public class Employee { private String firstName; private String middleName; private String lastName; }
|
2. 提供 getter 方法
getter 方法用于获取私有字段的值。通常命名为 getFieldName()
的形式。
1 2 3
| public String getFirstName() { return firstName; }
|
3. 提供 setter 方法
setter 方法用于设置私有字段的值。通常命名为 setFieldName()
的形式。
1 2 3
| public void setFirstName(String firstName) { this.firstName = firstName; }
|
核心代码
以下是一个完整的 Java 类示例,展示了如何使用 getter 和 setter 方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| package com.highmark.productConfig.types;
public class Employee { private String firstName; private String middleName; private String lastName;
public String getFirstName() { return firstName; }
public void setFirstName(String firstName) { this.firstName = firstName; }
public String getMiddleName() { return middleName; }
public void setMiddleName(String middleName) { this.middleName = middleName; }
public String getLastName() { return lastName; }
public void setLastName(String lastName) { this.lastName = lastName; }
public String getFullName() { return this.getFirstName() + this.getMiddleName() + this.getLastName(); } }
|
在 Python 中,可以使用 property
来实现类似的功能:
1 2 3 4 5 6 7 8 9 10 11 12
| class Simple(object): def _get_value(self): return self._value - 1
def _set_value(self, new_value): self._value = new_value + 1
def _del_value(self): self.old_values.append(self._value) del self._value
value = property(_get_value, _set_value, _del_value)
|
最佳实践
1. 封装行为
通过 getter 和 setter 方法,可以将与获取或设置属性相关的行为封装起来,方便后续添加额外的功能,如验证逻辑。
1 2 3 4 5 6 7
| public void setSpeed(int speed) { if (speed > 100) { this.speed = 100; } else { this.speed = speed; } }
|
2. 隐藏内部表示
可以在 getter 和 setter 方法中隐藏属性的内部表示,同时使用另一种表示来暴露属性。
3. 控制访问级别
getter 和 setter 方法可以设置不同的访问级别,例如 get 方法可以是 public,而 set 方法可以是 protected。
4. 延迟加载
对于存储在数据库中的对象,可以使用 getter 方法实现延迟加载,只有在需要时才从数据库中获取对象。
1 2 3 4 5 6 7 8 9
| protected YourType _yourName = null; public YourType YourName { get { if (_yourName == null) { _yourName = new YourType(); return _yourName; } } }
|
常见问题
1. 破坏契约
在 setter 方法中添加验证逻辑可能会破坏之前的契约,因为这改变了方法的前置条件。因此,在添加验证逻辑时,需要谨慎考虑是否会影响现有代码。
2. 降低可读性
过多使用 getter 和 setter 方法可能会使代码变得复杂,降低代码的可读性。在简单的情况下,如果不需要额外的功能,可以直接使用公共字段。
3. 性能问题
虽然 getter 和 setter 方法的性能开销通常很小,但在性能敏感的场景下,可能需要考虑直接访问字段。不过,现代编程语言和编译器通常会对方法调用进行优化,性能差异可能并不明显。
4. 违反面向对象原则
在某些情况下,过度使用 getter 和 setter 方法可能会导致类变成简单的数据持有者,而失去了面向对象编程的本质。应该尽量让类提供有意义的操作,而不仅仅是字段的访问和修改。