Flutter-finalとconst

FlutterではなくDartのfinalとconstについて。

大まかのことについては以下に書かれているので、もうちょっと例題付きで日本語でわかりやすくまとめてみた。

A tour of the Dart language
A tour of all the major Dart language features.

ありがちなまとめだけど。

final

finalは変数に一度オブジェクトを設定すると、以降その変数名に異なるオブジェクトを代入できないもの。

しかし格納されているオブジェクト内の情報は書き換え可能。
なので「定数」として取り扱うのは間違いと考えられる。

void main() {
  final a = Hoge(Hage());
  a.test.value = 5;   // オブジェクトの中身の変更は可能。
  a = Hoge(Hage());   // 再代入は不可。
}

class Hoge {
  const Hoge(this.test);
  final Hage test;
}

class Hage {
  int value = 0;
}

例えば上のような実装。

final宣言したaのオブジェクトの中身のvalueは変更可能なのである。
aに再代入はできない。

これではさすがに本当の意味での定数として使用することはできないであろう。

const

コンパイル時にオブジェクトの中身まで決定され、それ以降(実行時含む)オブジェクトの中身さえ変更できない本来の意味での「定数」を実現している。

constな変数はfinalでもある。

const化可能なクラスを実装するのは結構面倒かも。
まずconstコンストラクタを持つ必要があるのだけど、それを持つにはクラス内メンバがfinalでそれがconstコンストラクタを持っている必要がある。

例えばfinalの項で説明したHogeはその条件を満たしていないのでconst化することはできない。

void main() {
  final a = Hoge(Hage1());
  a.test.value = 5; // オブジェクトの中身の変更は可能。
  const b = Hoge(Hage1()); // const化出来ない。
  const d = Hoge(const Hage2(1)); // オブジェクトの中身の中身がconst化なのでconstにできる
  print("${d.test.value}");
}

class Hoge {
  const Hoge(this.test);
  final Hage test;
}

abstract class Hage {
  const Hage();
  int get value;
  set value(int val);
}

/// Hageを継承しているけどconstコンストラクタを持っていない
class Hage1 extends Hage {
  int _value = 0;
  @override
  int get value => _value;
  @override
  set value(int val) {
    _value = val;
  }
}

class Hage2 extends Hage {
  const Hage2(this._value);
  final int _value;
  @override
  int get value => _value;
  @override
  set value(int val) {}
}

例えば上の実装では変数dのHage2を入れたHogeはconst化出来ている。
これはHage2側の変数がfinalでその変数の中身も変更不可で、さかのぼりHoge内のtestもfinalで変更不可、だからconst化出来るという結果になる。

しかしconstコンストラクタを持たず変数がfinalになっていないHage1を入れている変数bはconst宣言できない。

コメント

タイトルとURLをコピーしました