[TOC]
下面的最佳实践描述了如何在Dart中最好地使用变量。
## 不要显式地将变量初始化为空。
在Dart中,未显式初始化的变量或字段自动被初始化为null。这是由语言可靠地指定的。在Dart中没有“未初始化内存”的概念。添加= null是多余的和不需要的。
~~~
int _nextId;
class LazyId {
int _id;
int get id {
if (_nextId == null) _nextId = 0;
if (_id == null) _id = _nextId++;
return _id;
}
}
~~~
以下是不推荐的写法:
~~~
int _nextId = null;
class LazyId {
int _id = null;
int get id {
if (_nextId == null) _nextId = 0;
if (_id == null) _id = _nextId++;
return _id;
}
}
~~~
## 避免储存你能计算的东西。
在设计类时,您通常希望将多个视图公开到相同的底层状态。通常你会看到在构造函数中计算所有视图的代码,然后存储它们:
应该避免的写法:
~~~
class Circle {
num radius;
num area;
num circumference;
Circle(num radius)
: radius = radius,
area = pi * radius * radius,
circumference = pi * 2.0 * radius;
}
~~~
这个代码有两个问题。首先,它可能会浪费内存。严格地说,这个区域和周长是缓存。它们是存储的计算,我们可以从已有的其他数据中重新计算。他们用增加的内存换取减少的CPU使用。我们知道我们有一个性能问题值得权衡吗?
更糟糕的是,代码是错误的。缓存的问题是无效——您如何知道何时缓存过期需要重新计算?在这里,我们永远不会这样做,即使半径是可变的。您可以指定一个不同的值,而面积和周长将保留它们以前的、现在不正确的值。
为了正确处理缓存失效,我们需要这样做:
应该避免的写法:
~~~
class Circle {
num _radius;
num get radius => _radius;
set radius(num value) {
_radius = value;
_recalculate();
}
num _area;
num get area => _area;
num _circumference;
num get circumference => _circumference;
Circle(this._radius) {
_recalculate();
}
void _recalculate() {
_area = pi * _radius * _radius;
_circumference = pi * 2.0 * _radius;
}
}
~~~
这需要编写、维护、调试和读取大量代码。相反,您的第一个实现应该是:
~~~
class Circle {
num radius;
Circle(this.radius);
num get area => pi * radius * radius;
num get circumference => pi * 2.0 * radius;
}
~~~
这段代码更短,占用的内存更少,也更不容易出错。它存储表示圆所需的最小数据量。没有字段可以不同步,因为只有一个真实的源。
在某些情况下,您可能需要缓存慢速计算的结果,但只有在知道存在性能问题之后,才能这样做,请仔细执行,并留下解释优化的注释。