final 与 const 字段
本课属于 Coddy Dart 学习旅程的“面向对象编程”单元。第 18 课,共 110 课。
在类中声明字段时,你可以使用 final 或 const 来控制初始化后值是否可以更改。两者都会创建不可变的值,但它们的工作方式不同。
final 字段只能设置一次,但它的值是在运行时确定的。你可以在声明时为它赋值,也可以通过构造函数赋值:
class Person {
final String name;
final DateTime createdAt = DateTime.now();
Person(this.name);
}
Person p = Person('Alice');
// p.name = 'Bob'; // 错误:不能重新给 final 字段赋值创建对象时会设置 name,而 createdAt 会记录当前时间。初始化后,这两个值都会锁定。
static const 字段的值必须在编译时已知。它属于类本身,并由所有实例共享:
class Circle {
static const double pi = 3.14159;
final double radius;
Circle(this.radius);
double get area => Circle.pi * radius * radius;
}关键区别:final 字段可以保存运行时计算出的值(例如 DateTime.now()),而 const 要求值在编译时确定。实例字段不能直接声明为 const,类级别只允许使用 static const。
挑战
简单让我们构建一个产品目录系统,展示 final 和 static const 字段之间的区别。你将创建具有不可变属性和共享配置值的产品。
你将把代码整理到两个文件中:
product.dart:定义一个表示商店商品的Product类。这个类应包含:- 一个设为
0.08的static const double taxRate(所有产品共用的 8% 税率) - 一个设为
'USD'的static const String currency - 一个用于保存产品名称的
final String name(通过构造函数设置) - 一个用于保存产品基础价格的
final double basePrice(通过构造函数设置) - 一个
final String sku(库存单位),它将前缀与产品名称组合起来,并在初始化列表中计算,方式为先写'SKU-',再接上大写形式的名称 - 一个接收
name和basePrice的构造函数 - 一个用于计算含税价格的 getter
priceWithTax - 一个用于打印产品信息的
display()方法
- 一个设为
main.dart:导入产品类并创建两个产品:- 一个基础价格为
999.99的'Laptop' - 一个基础价格为
29.99的'Mouse'
display()。- 一个基础价格为
display() 方法应按以下确切格式打印:
[sku] - [name]: [basePrice] [currency] (with tax: [priceWithTax] [currency])显示时,使用 toStringAsFixed(2) 将 priceWithTax 四舍五入到小数点后 2 位。
预期输出:
SKU-LAPTOP - Laptop: 999.99 USD (with tax: 1079.99 USD)
SKU-MOUSE - Mouse: 29.99 USD (with tax: 32.39 USD)亲手试试
import 'product.dart';
void main() {
// TODO: 创建一个名为 'Laptop' 的 Product,基础价格为 999.99
// TODO: 创建一个名为 'Mouse' 的 Product,基础价格为 29.99
// TODO: 依次对每个产品调用 display()(先 Laptop,后 Mouse)
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Dart 在线编译器