LoginSignup
0
1

Dartのジェネリクスは共変である

Last updated at Posted at 2021-11-14

Dartのジェネリクスは共変

タイトルでオチがついている。Dartのジェネリクスって共変なんだねえ。

The Dart type system | Dart
https://dart.dev/guides/language/type-system#generic-type-assignment

共変って何?

あるクラスTsuperがサブクラスTsubをもつ場合に、

  • Tsuperによる総称型にTsubによる総称型を代入できることを共変といいます
    • Dartはこれに該当するということです。
  • 対して、Tsuper型の変数にTsub型の変数を代入できないことを不変といいます
    • Javaがこれに該当します。

具体的なコードによる説明

ジェネリクス型に互換性があり、代入ができるということを共変といいます
dartは互換性があるので共変です

dart
List<num> numList;
List<double> doubleList = [];

numList = doubleList; // 代入ができる。これが共変

一見この互換性は便利そうですが、以下のようなリスクがあります。

dart
List<num> numList;
List<double> doubleList = <double>[]; // [];の丁寧な書き方

numList = doubleList; // 代入ができる

// コンパイルこそ通るものの、
// doubleのリストにintをaddすることによって実行時エラーが発生する。
// 変数にnumListって書いてあるから動きそうなのにね。
numList.add(2 as int); // 実行時エラー!

ちなみにJavaはジェネリクス型に互換性がありません(不変)1

java
List<Number> numberList;
List<Double> doubleList;

// numberList = doubleList; // コンパイルエラー

Flutterにおける身近な共変の利用

例えばこういう画面クラス。
createState()について、MyStateの型はState<MyPage>であるにもかかわらず、State<StatefulWidget> という戻り値として成立していますね。

State<StatefulWidget>State<MyPage> であり、State<MyPage>State<StatefulWidget> として扱ってよいことになっているので、この書き方が許容されます。

dart
class MyPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return MyState();
  }
}

class MyState extends State<MyPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(body: Text("this is view"));
  }
}

MyPage.createState()の中身を冗長に書くとこういう風になります。

dart
class MyPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    State<StatefulWidget> returnValue;
    State<MyPage> myState = MyState();
    returnValue = myState; // 共変なので代入ができる
    return returnValue;
  }
}

class MyState extends State<MyPage> {
  // (略)
}
  1. この制約を緩めて使いやすくするために、型の設計者はextendsとかsuperとかワイルドカードとかの署名をこねくり回します。

0
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1