根據this excellent explanationconst
Dart中的表達式是「深不可變的」,這意味着裏面沒有任何東西可以改變,因此整個表達式總是表示相同的東西。這對於編譯器非常有用,因爲它可以一次生成整個對象圖形,並在每次出現這種表達時重新使用它,而且程序員知道這樣一個表達式 - 即使是深度嵌套 - 仍然是靜止的遵循價值語義,不會在我背後做任何事情。Const構造函數與靜態最終規範值
我正在使用編譯器的這些優化來使用一個結構良好的對象模型(而不是在位向量中手動編碼它),並且仍然獲得良好的性能。既然我們可以通過用「明確散列」某些值來獲得其中的一些好處,使用它們的運行時常量,這個問題就出現了,在這種情況下,哪個是好的風格?
請看下面的例子:
enum ShaftType { RING, SUN, CARRIER }
class Shaft {
final int index;
final ShaftType type;
Shaft(this.type, this.index) {
assert((type == ShaftType.CARRIER) == (index == null));
}
const Shaft.CARRIER()
: type = ShaftType.CARRIER,
index = null;
const Shaft.RING(this.index) : type = ShaftType.RING;
const Shaft.SUN(this.index) : type = ShaftType.SUN;
}
class GearPath {
final Shaft input, output, fixed;
GearPath({this.input, this.output, this.fixed}) {
// input and output must be set
assert(null != input && null != output);
// fixed shaft can't be anything else
assert(fixed != input && fixed != output);
}
GearPath.carrierToFirstRingFixedSun(int i)
: input = const Shaft.CARRIER(),
output = const Shaft.RING(0),
fixed = new Shaft.SUN(i) {}
static final singleFixedSunUp = new GearPath(
input: const Shaft.CARRIER(),
output: const Shaft.RING(0),
fixed: const Shaft.SUN(0),
);
static final directDrive = new GearPath(
input: const Shaft.CARRIER(),
output: const Shaft.CARRIER(),
fixed: null,
);
// ...
}
我不能讓主Shaft(..)
和GearStage(..)
構造const
,因爲我要檢查一些限制,但我可以提供特殊構造的情況下(如Shaft.SUN(int i)
,Shaft.CARRIER()
),它們通過設計符合這些限制(至少部分),併爲用戶提供對這些共同價值的可讀短文。
另一方面,當一個const
構造函數沒有參數時,我就可以像GearStage.directDrive
那樣將它寫成static final
成員。如果所有用戶都引用此靜態成員而不是再次重新創建值,那麼我們還可以享受共享內存和快速比較(引用同一對象)的好處。我無法將此定義的右側聲明爲const,因爲它使用非常量構造函數,但是開發人員可以從上下文中看到,這確實是一個常量值,而不是靜態字段中隱藏的全局可變單例。所以出於實際的目的,它應該和const構造函數一樣好,對吧?
由於我沒有發現這描述了任何作爲最佳實踐的地方,我的問題就是如果這確實是一種在const
構造函數和static final
「命名值實例」之間進行組合和折衷的好方法?
最後,我想知道是否有一種方法可以將GearPath.carrierToFirstRingFixedSun(int i)
也作爲一個const構造函數聲明?目前我不能因爲const Shaft.SUN(i)
抱怨i
不是恆定的。