LoginSignup
1

More than 1 year has passed since last update.

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は互換性があるので共変です

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における身近な共変の利用

例えばこういう画面クラス。

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とかワイルドカードとかの署名をこねくり回します(作る側は面倒くさい)。 

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
What you can do with signing up
1