定数の宣言
Flutter もとい Dartには、多くの言語と同じように2種類の定数の宣言方法があります。定数とは、一度宣言したら、後で再代入できないものです。こちらは、その違いは何で、どのように使い分けていけば良いでしょうか。
final/const
// 使い方
final int value1 = 1;
final value2 = 2;
const int value3 = 3;
const value4 = 4;
// 以下はコンパイルエラー
value1 = 5;
value3 = 6
final とconst の違い
finalは実行時に定数を確定させます。一方でconstはコンパイル時に定数を確定させます。いやあ、よく分かりませんね。
逆に言うと、constはコンパイル時に値が決まっていないといけないのです。
例えば、クラス内にメンバー変数をfinalとして定義しますが、constにはできません。コンストラクタで引数として、外側から値を与えられるので、コンパイル実施時には値が決まらないからです。
一方で、クラス変数としてはstatic constという形で宣言できます。こちらは、コンパイル実行時に値が決まるので、constにできます。
class TestClass{
final int memberValue;
static const int classValue = 1;
TestClass(this.memberValue);
}
なるべくconstを使おう
constはコンパイル時に値が決定されます。そのため、再生成しないことが決まりますので、メモリーの確保が一度ですむので、動作が軽くなります。
よく言われるのが、FlutterのWidgetはなるべくconstにした方が良い、ということでしょう。一度生成されたら、再生成されることがないことが保証されています。そのため、該当のWidgetを再生成する必要するかどうか、Flutter側で判断するコストが軽くなり、また、そのWidgetの子Widgetを再生する必要があるか判断する必要性もなくなります。そのため、全体としてアプリが軽くなります。
Listではちょっと動作が異なる
さて、以下のコードを実行すると、どうなるでしょうか。
final finalList = [1, 2, 3];
finalList.add(4);
const constList = const [1, 2, 3];
constList.add(4);
constList.add(4)で、UnsupportedError(“Cannot add to an unmodifiable list”) が発生します。
finalはあくまで再代入できないだけなので、finalList.add(4)が実行できます。finalで宣言したクラスでも、メンバー変数を変更できますよね。
一方で、constの場合は、コンパイル実行時に値が定数化されているので、実行時に例外が発生します。(残念ながら、コンパイル時にエラー検出してくれない)
まとめ
以上でconstとfinalの違いを説明しました。私も昔C#で検索したなぁ、と懐かしく思ってます。参考になれば、幸いです。