字
字节笔记本
2026年3月22日
Dart 构造函数完全指南:默认、命名、常量、工厂构造函数详解
这篇文章将详细介绍 Dart 语言中的构造函数类型,包括默认构造函数、命名构造函数、常量构造函数、工厂构造函数等,并通过示例讲解构造函数的初始化列表、重定向和继承机制。
默认构造函数
dart
class Person {
String name;
int age;
// 默认(无名)构造函数
Person(this.name, this.age);
}
// 使用
var p = Person('张三', 25);当没有显式定义构造函数时,Dart 会提供一个默认的无参构造函数。
命名构造函数
Dart 允许定义多个命名构造函数,类似于其他语言的函数重载:
dart
class Point {
double x, y;
Point(this.x, this.y);
// 命名构造函数 - 从 JSON 创建
Point.fromJson(Map<String, double> json)
: x = json['x'],
y = json['y'];
// 命名构造函数 - 原点
Point.origin()
: x = 0,
y = 0;
}
// 使用
var p1 = Point(3, 4);
var p2 = Point.fromJson({'x': 1, 'y': 2});
var p3 = Point.origin();常量构造函数
使用 const 关键字修饰的构造函数,所有实例字段必须是 final 的:
dart
class ImmutablePoint {
final double x;
final double y;
const ImmutablePoint(this.x, this.y);
static final ImmutablePoint origin = const ImmutablePoint(0, 0);
}
// 编译时常量,所有 const 创建的相同参数对象是同一个实例
var p1 = const ImmutablePoint(1, 1);
var p2 = const ImmutablePoint(1, 1);
print(identical(p1, p2)); // true工厂构造函数
工厂构造函数不会总是创建新实例,可以从缓存中返回已有实例:
dart
class Logger {
final String name;
bool _isInit = false;
// 私有构造函数
Logger._internal(this.name);
// 工厂构造函数
static final Map<String, Logger> _cache = {};
factory Logger(String name) {
return _cache.putIfAbsent(name, () => Logger._internal(name));
}
}
// 多次调用返回同一个实例
var logger1 = Logger('UI');
var logger2 = Logger('UI');
print(identical(logger1, logger2)); // true工厂构造函数的关键特点:
- 使用
factory关键字声明 - 不能使用
this参数 - 必须显式返回一个实例
- 适合实现单例模式、缓存等场景
重定向构造函数
一个构造函数可以重定向到同类的另一个构造函数:
dart
class Rectangle {
double width, height;
Rectangle(this.width, this.height);
// 重定向到主构造函数
Rectangle.square(double size) : this(size, size);
}初始化列表
构造函数体执行之前,可以初始化实例变量。初始化列表用冒号 : 分隔:
dart
class Rectangle {
double width, height;
// 通过初始化列表计算最终值
Rectangle.fromJson(Map<String, double> json)
: width = json['w'] * 2,
height = json['h'] * 2 {
print('Width: $width, Height: $height');
}
// 初始化列表中调用父类构造函数
Rectangle.withColor(double w, double h, Color color)
: width = w,
height = h,
super(color);
}初始化列表的使用场景:
- 设置
final字段的值 - 调用父类的构造函数
- 使用
assert进行参数校验
dart
class Point {
final double x;
final double y;
Point({required double x, required double y})
: assert(x >= 0),
assert(y >= 0),
this.x = x,
this.y = y;
}构造函数继承与 super
子类构造函数必须调用父类构造函数。如果父类没有无名无参构造函数,子类必须手动调用:
dart
class Animal {
String name;
Animal(this.name);
}
class Dog extends Animal {
String breed;
// 显式调用父类构造函数
Dog(String name, this.breed) : super(name);
}如果父类有无名无参构造函数,子类会自动隐式调用。也可以使用级联调用:
dart
class View {
View();
}
class MyView extends View {
MyView() : super();
}GetX 中的构造函数实践
在 GetX 框架中,Get.put() 和 Get.lazyPut() 经常结合工厂模式使用:
dart
class Controller extends GetxController {
static Controller get to => Get.find<Controller>();
}
// 使用工厂构造函数确保单例
class AppBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => Controller());
}
}构造函数对比总结
| 类型 | 关键字 | 特点 | 适用场景 |
|---|---|---|---|
| 默认构造函数 | 类名 | 最多一个 | 基本实例化 |
| 命名构造函数 | 类名.名称 | 可定义多个 | 不同初始化方式 |
| 常量构造函数 | const | 编译时常量 | 不可变对象 |
| 工厂构造函数 | factory | 可返回缓存实例 | 单例、缓存 |
| 重定向构造函数 | : this() | 转发到其他构造函数 | 简化代码 |
分享: