この章のおもちゃ パイの素材が重なる イメージ Top Top Bot Tuna Salmon Fish Pie フルーツが連なる イメージ 分岐が発⽣する + Fruit Tree Flat Apple Flat Lemon Bud Flat Apple Split Flat Flat Bud Bud Lemon Peach Fruit Tree 分岐がない 分岐がある 線形リスト 線形リスト 線形リスト + 2分⽊
bTreeVisitor forBud() : boolean forFlat( f : Fruit, t : Tree ) : boolean forSplit( l : Tree, r : Tree ) : boolean Concrete Visitors accept それぞれビジター内の⾃分⽤のクラスのメソッドを呼び出す Tree accept( ask : bTreeVisitor ) : boolean Bud Flat f : Fruit t : Tree Split l : Tree r : Tree ビジターの振る舞いを集約
l と r の両⽅がスプリット⽊かどうか確認しなきゃなら ないんだよね。 本⽂ p.103 Split/Bud だけか Flat が1つも無いか ⽅針: Flat か Bud まで探索を続ける Flat が1つでも⾒つかれば false l r Split Flat ではないがさらに下の⽊に Flat があるかもしれない 調べるべき⽊が2つある r l
int を⽣成するようなビジターのイン ターフェースを定義しよう。 bTreeVisitorI と殆ど同じだね。 本⽂ p.107 <<interface>> bTreeVisitor forBud() : boolean forFlat( f : Fruit, t : Tree ) : boolean forSplit( l : Tree, r : Tree ) : boolean bIsFlat <<interface>> iTreeVisitor forBud() : int forFlat( f : Fruit, t : Tree ) : int forSplit( l : Tree, r : Tree ) : int iHeight bIsSplit bHasFruit
accept メソッドを TreeD に追加できるね。 それは同じ名前の2つのメソッドを1つの クラスに持つ事が出来るってことかな? † † Javaでは同じ名前で異なる型の⼊⼒を持つ複数のメソッドを定義 する事は「オーバーロード」と呼ばれます。 本⽂ p.107 Tree accept( ask : bTreeVisitor ) : boolean accpet( ask : iTreeVisitor ) : int <<interface>> bTreeVisitor forBud() : boolean forFlat( f : Fruit, t : Tree ) : boolean forSplit( l : Tree, r : Tree ) : boolean <<interface>> iTreeVisitor forBud() : int forFlat( f : Fruit, t : Tree ) : int forSplit( l : Tree, r : Tree ) : int accept
のバリアントに新しい accept メソッドを追加しよ うか。簡単なものから始めよう。 これは簡単さ。 本⽂ p.107 Tree accept( ask : bTreeVisitor ) : boolean accpet( ask : iTreeVisitor ) : int Bud <<interface>> bTreeVisitor forBud() : boolean forFlat( f : Fruit, t : Tree ) : boolean forSplit( l : Tree, r : Tree ) : boolean <<interface>> iTreeVisitor forBud() : int forFlat( f : Fruit, t : Tree ) : int forSplit( l : Tree, r : Tree ) : int accept Bud⽤ を実⾏ Bud⽤ を実⾏
accept( ask : bTreeVisitor ) : boolean accpet( ask : iTreeVisitor ) : int <<interface>> bTreeVisitor forBud() : boolean forFlat( f : Fruit, t : Tree ) : boolean forSplit( l : Tree, r : Tree ) : boolean <<interface>> iTreeVisitor forBud() : int forFlat( f : Fruit, t : Tree ) : int forSplit( l : Tree, r : Tree ) : int accept Flat⽤ を実⾏ Flat f : Fruit t : Tree Split l : Tree r : Tree Flat⽤ を実⾏ Split⽤ を実⾏ Split⽤ を実⾏
そのメソッドは int でも boolean でもなく TreeD を⽣ 成するから、また別のインターフェースを追加する必 要があるんだよね。 本⽂ p.109 tSubstV ( , ) TreeD <<interface>> bTreeVisitor forBud() : boolean forFlat( f : Fruit, t : Tree ) : boolean forSplit( l : Tree, r : Tree ) : boolean <<interface>> iTreeVisitor forBud() : int forFlat( f : Fruit, t : Tree ) : int forSplit( l : Tree, r : Tree ) : int <<interface>> tTreeVisitor forBud() : Tree forFlat( f : Fruit, t : Tree ) : Tree forSplit( l : Tree, r : Tree ) : Tree
TreeD はどうかな。 簡単さ。これが抽象的な定義だよ。 本⽂ p.109 Tree accept( ask : bTreeVisitor ) : boolean accpet( ask : iTreeVisitor ) : int accept( ask : tTreeVisitor ) : Tree <<interface>> bTreeVisitor forBud() : boolean forFlat( f : Fruit, t : Tree ) : boolean forSplit( l : Tree, r : Tree ) : boolean <<interface>> iTreeVisitor forBud() : int forFlat( f : Fruit, t : Tree ) : int forSplit( l : Tree, r : Tree ) : int <<interface>> tTreeVisitor forBud() : Tree forFlat( f : Fruit, t : Tree ) : Tree forSplit( l : Tree, r : Tree ) : Tree accept
: bTreeVisitor ) : boolean accpet( ask : iTreeVisitor ) : int accept( ask : tTreeVisitor ) : Tree <<interface>> bTreeVisitor forBud() : boolean forFlat( f : Fruit, t : Tree ) : boolean forSplit( l : Tree, r : Tree ) : boolean <<interface>> iTreeVisitor forBud() : int forFlat( f : Fruit, t : Tree ) : int forSplit( l : Tree, r : Tree ) : int Flat f : Fruit t : Tree Split l : Tree r : Tree <<interface>> tTreeVisitor forBud() : Tree forFlat( f : Fruit, t : Tree ) : Tree forSplit( l : Tree, r : Tree ) : Tree Bud accept 本⽂ p.110
bTreeVisitor forBud() : boolean forFlat( f : Fruit, t : Tree ) : boolean forSplit( l : Tree, r : Tree ) : boolean bIsFlat <<interface>> iTreeVisitor forBud() : int forFlat( f : Fruit, t : Tree ) : int forSplit( l : Tree, r : Tree ) : int iHeight bIsSplit bHasFruit <<interface>> tTreeVisitor forBud() : Tree forFlat( f : Fruit, t : Tree ) : Tree forSplit( l : Tree, r : Tree ) : Tree tSubst n : Fruit o : Fruit Tree accept( ask : bTreeVisitor ) : boolean accpet( ask : iTreeVisitor ) : int accept( ask : tTreeVisitor ) : Tree accept
bTreeVisitor forBud() : boolean forFlat( f : Fruit, t : Tree ) : boolean forSplit( l : Tree, r : Tree ) : boolean bIsFlat <<interface>> iTreeVisitor forBud() : int forFlat( f : Fruit, t : Tree ) : int forSplit( l : Tree, r : Tree ) : int iHeight bIsSplit bHasFruit <<interface>> tTreeVisitor forBud() : Tree forFlat( f : Fruit, t : Tree ) : Tree forSplit( l : Tree, r : Tree ) : Tree tSubst n : Fruit o : Fruit Tree accept( ask : bTreeVisitor ) : boolean accpet( ask : iTreeVisitor ) : int accept( ask : tTreeVisitor ) : Tree accept iOccurs a : Fruit
とそのバリアントにほぼ同⼀の種類の accept が3つあるのって気にならない? 定義をコピペするのはいつも良く無いことなんだよね。 もしミスをした上でコピーしちゃったら、ミスをコ ピーするって事になるもんね。もしそれを変更したら、 コピペした他の部分も変更しなきゃならないのを忘れ るかもしれない。 本⽂ p.112 Tree accept( ask : bTreeVisitor ) : boolean accpet( ask : iTreeVisitor ) : int accept( ask : tTreeVisitor ) : Tree <<interface>> bTreeVisitor forBud() : boolean forFlat( f : Fruit, t : Tree ) : boolean forSplit( l : Tree, r : Tree ) : boolean <<interface>> iTreeVisitor forBud() : int forFlat( f : Fruit, t : Tree ) : int forSplit( l : Tree, r : Tree ) : int <<interface>> tTreeVisitor forBud() : Tree forFlat( f : Fruit, t : Tree ) : Tree forSplit( l : Tree, r : Tree ) : Tree accept
: TreeVisitor ) : Object <<interface>> TreeVisitor forBud() : Object forFlat( f : Fruit, t : Tree ) : Object forSplit( l : Tree, r : Tree ) : Object Flat f : Fruit t : Tree Split l : Tree r : Tree Bud accept 旧 新 本⽂ p.112