Dart含计算字段的不可变类:如何用多构造器生成const对象?
在Dart中实现支持const的三点构造Circle类
要实现支持const的三点构造Circle类,核心是利用Dart 2.14+引入的const静态函数,配合const命名构造器完成编译时计算,同时保持对象不可变性。
解决方案代码
import 'dart:math'; class Circle { final Point center; final double radius; // 基础const构造器 const Circle(this.center, this.radius); // 支持const的三点命名构造器 const Circle.fromPoints(Point p1, Point p2, Point p3) : center = _getCenter(p1, p2, p3), radius = _getCenter(p1, p2, p3).distanceTo(p1); // const静态方法:必须是纯函数,无副作用,仅依赖编译时常量参数 static const Point _getCenter(Point p1, Point p2, Point p3) { // 三点求圆心的数学实现(确保逻辑纯、无运行时依赖) final ax = p1.x, ay = p1.y; final bx = p2.x, by = p2.y; final cx = p3.x, cy = p3.y; final d = 2 * (ax * (by - cy) + bx * (cy - ay) + cx * (ay - by)); final ux = ((ax*ax + ay*ay) * (by - cy) + (bx*bx + by*by) * (cy - ay) + (cx*cx + cy*cy) * (ay - by)) / d; final uy = ((ax*ax + ay*ay) * (cx - bx) + (bx*bx + by*by) * (ax - cx) + (cx*cx + cy*cy) * (bx - ax)) / d; return Point(ux, uy); } }
关键说明
- const命名构造器:
Circle.fromPoints被声明为const,要求所有初始化逻辑必须在编译时完成,不能包含运行时代码块。 - const静态函数:
_getCenter必须标记为const,确保它是纯函数——只接收编译时常量参数,执行无副作用的数学运算,返回编译时常量结果。 - 使用方式:当传入的三个
Point都是const实例时,可直接生成const Circle对象:
void main() { const p1 = Point(-1, 0); const p2 = Point(0, 1); const p3 = Point(1, 0); const circle = Circle.fromPoints(p1, p2, p3); print(circle.center); // 输出 (0.0, 0.0) print(circle.radius); // 输出 1.0 }
为什么之前的方法行不通?
- 工厂构造器:工厂构造器无法被标记为
const,因为它允许执行运行时逻辑,因此无法生成const实例。 - 外部计算失败:之前的
getCenter如果不是const方法,计算出的center变量是运行时变量,无法传入const Circle构造器(const构造器只接受编译时常量参数)。
局限性
如果三点求圆心的逻辑依赖运行时状态(比如动态输入、随机值等),则无法使用const构造器,此时只能用工厂构造器生成不可变对象(保留final字段),但无法获得const实例的编译时优化。
内容的提问来源于stack exchange,提问作者Jan Tosovsky
相关产品推荐
相关产品推荐

