在 Dart 中,getter 和 setter 是用于访问对象的属性的特殊方法。通过 getter 和 setter,你可以控制如何读取和修改对象的属性,这为对象提供了更高的封装性和灵活性。
一、 Getter(获取器)
Getter 用于获取对象的属性值。它是一个特殊的方法,通过 get
关键字来定义,通常用来让外部访问对象的私有属性。getter 允许你通过像访问字段一样访问方法,但实际上它是执行方法逻辑来返回值。
例子:
class Person {
String? _name;
Person(this._name);
// Getter
String? get name =>_name;
// 如果不希望外部代码直接修改,可以提供只读的getter
}
void main() {
var person = Person('Alice');
print(person.name); // 通过 getter 访问
//person.name = "siri"; //报错不能修改
}
在这个例子中,name
就是一个 getter,你可以像访问字段一样访问它,但实际上它是通过 _name
属性来获取数据的。
二、Setter(设置器)
Setter 用于设置对象的属性值。它是一个特殊的方法,通过 set
关键字来定义。setter 通常用于在设置对象的属性时进行额外的逻辑处理,如验证输入、修改值等。
例子:
class Person {
String? _name;
Person(this._name);
// Getter
String? get name =>_name;
// Setter _name 是可空的 设置值时也必须时可空的 String? 可以省略不写 写了就一定要带?
set name(String? value) {
if (value.isEmpty) {
print('Name cannot be empty');
} else {
_name = value;
}
}
}
void main() {
var person = Person('Alice');
print(person.name); // 使用 getter 访问
// 使用 setter 设置值
person.name = 'Bob'; // 通过 setter 设置
print(person.name); // 输出 Bob
person.name = ''; // 输出 Name cannot be empty
}
在上面的例子中,name
既有 getter 又有 setter。getter 用来获取 _name
属性的值,而 setter 用来设置 _name
的值,同时添加了一些逻辑来确保名字不会为空。
简化的 Setter
在 Dart 中,你也可以为单一属性创建简化版的 getter 和 setter,这样写法更加简洁。
例子:
class Person {
String? _name;
Person(this._name);
// Getter
String? get name => _name;
// 简化版 Setter
set name(String? value) => _name = value;
}
void main() {
var person = Person('Alice');
print(person.name); // 输出 Alice
person.name = 'Bob'; // 设置新名字
print(person.name); // 输出 Bob
}
这个例子中使用了 Dart 提供的简化语法,代码更加简洁。
三、只读 Getter 和只写 Setter
你可以选择只实现 getter 或 setter,从而使某个属性只能被读取或只能被设置。
只读 Getter:
class Person {
String? _name;
Person(this._name);
// 只读 getter
String? get name => _name;
}
void main() {
var person = Person('Alice');
print(person.name); // 只可以读取 name person.name = "..." 会报错
}
只写 Setter:
class Person {
String? _name;
Person(this._name);
// 只写 setter
set name(String? value) => _name = value;
}
void main() {
var person = Person('Alice');
person.name = 'Bob'; // 只可以设置 name
print(person.name); //读取会报错
}
四、getter 和 setter 的用法场景
- 数据封装:通过 getter 和 setter,可以控制访问和修改数据的方式,保护内部实现的细节,避免外部直接修改对象的私有属性。
- 输入验证:在 setter 中,可以添加逻辑来验证输入数据的有效性。
- 延迟计算:有时你不希望在属性访问时直接存储数据,而是根据其他字段的值动态计算一个值,这时可以使用 getter 来实现延迟计算。
例子:计算属性
class Rectangle {
double width, height;
Rectangle(this.width, this.height);
// 计算属性:面积(不需要存储,动态计算)
double get area => width * height;
}
void main() {
var rectangle = Rectangle(5, 10);
print(rectangle.area); // 输出 50
}
在上面的例子中,area
并不是一个实际存储的属性,而是通过 width
和 height
计算得出的。这是一个典型的使用 getter 进行计算的例子。
总结
- getter 用于返回对象的属性值,它通过
get
关键字定义。 - setter 用于设置对象的属性值,它通过
set
关键字定义。 - getter 是只读的 setter 是只写的。