Dart(Flutter)のIterable,iteratorについて調べています。
Iterable,iteratorなどのざっくりとした仕組みについてはつかめたのですが、
Iterableの代表的な型であるList型について、ソースコードを見ると、
↓まず、List<E>クラスが抽象クラスEfficientLengthIterable<E>クラスを実装している。
List<E>クラス内にiteratorプロパティに関する記述がない。
コンストラクタで初期化しているようなコードも見当たらない。
//list.dart abstract class List<E> implements EfficientLengthIterable<E> { ...
↓EfficientLengthIterable<T>クラスのスーパークラスがIterable<T>クラス。
EfficientLengthIterable<T>自体にはiteratorプロパティの実装コードはない。
(少し下にListIterable<E>クラスが定義されており、ListIterableクラスにはiteratorプロパティの初期化コードがある。
しかしList<E>クラスがListIterable<E>を継承などしているようなコードが見当たらない。)
//internal/iterable.dart abstract class EfficientLengthIterable<T> extends Iterable<T> { const EfficientLengthIterable(); int get length; } abstract class ListIterable<E> extends EfficientLengthIterable<E> { ...
↓Iterable<E>クラスのiteratorプロパティは宣言されているが、宣言されているだけで初期化はされていない。(抽象クラスなので、それが普通だと思いますが。)
//core/iterable.dart abstract class Iterable<E> { ... Iterator<E> get iterator; ...
ざっと見るとこういう感じで、これだとList<E>クラスのインスタンスのiteratorプロパティは初期化されてないのでnullになってしまうような気がします。
それだとリストのイテレートもできないと思うのですが、
実際は(当然のように)普通にイテレートできます。
EfficientLengthIterable<T>クラスの定義の下に
ListIterable<E>クラス
ListIterator<E>クラス
などの定義があり、List<E>クラスがListIterable<E>クラスを継承していれば辻褄が合うように思います。
(細かく見たわけではないですが、ざっくりと見て辻褄が合いそうな感じはします。)
名前を見ても継承してそうな感じがします(笑)
でもそのような関係性を示すコードが見当たりません。
普通に見るとクラス階層は、
スーパークラス ← Iterable<E> ← EfficientLengthIterable<T> ← List<E> ←サブクラス
のようにしか見えません。
(implementsが使われているので、List<E>はEfficientLengthIterable<T>のサブクラスではありませんが。)
上記のクラス階層だと、ListIterable<E>のメンバ(ListIteratorインスタンスで初期化されたiteratorプロパティ)をList<E>が継承することはできないですよね。
どこか他の場所でList<E>クラスとListIterable<E>クラスの関係性を示すコードがあるのでしょうか?
それともこのコードでList<E>クラスのインスタンスのiteratorプロパティは適切に初期化されるのでしょうか?
2020/11/29/15:30追記
質問の主旨なのですが、
iterable、iteratorなどの基本を学ぶ中で、
リストリテラルなどで生成したList<E>型のインスタンスがfor-inループでイテレートできる以上、List<E>インスタンス内のiteratorプロパティに有効なIterator<E>(あるいはそのサブクラス)のインスタンスがセットされているはずなので、それをソースコードで確認したい、
という考えが発生しました。
それを確認するためにソースコードのどこを見れば良いか、ということが質問の主旨です。
リストリテラルで生成されるリストがList<E>型のコンストラクタで生成されるとすると、
結局List<E>クラスのコンストラクタが、(toast-uz様にお示し頂いた)Iterable.generate()コンストラクタを呼び出しているなら、
ListIterableのサブクラスが生成されるので、全てつながると思うのですが、
List<E>クラスのコンストラクタを見ると
external factory List.filled(int length, E fill, {bool growable = false});
のようにコンストラクタは全てexternal修飾子がついていて、ボディが記述されていないようです。
externalというのは、メソッド(コンストラクタ)のボディは別の場所で定義されている、ということらしいのですが、
その場所ってどこなのでしょうか?
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/11/29 03:33
2020/11/29 03:55 編集
2020/11/29 05:45
2020/11/29 06:22 編集