Upgrade to Pro — share decks privately, control downloads, hide ads and more …

A Little Java, a Few Patterns -Ch.7 Oh, My!-

rpaka
December 01, 2020

A Little Java, a Few Patterns -Ch.7 Oh, My!-

講義での発表資料です。
This is my presentation material of lecture.

rpaka

December 01, 2020
Tweet

More Decks by rpaka

Other Decks in Programming

Transcript

  1. 愛知県⽴⼤学 情報科学研究科 神⾕幸宏研究室 † ⼩久保 律樹‡ Rev. Chapter. 7 Oh

    My! I LEC 20F SA01 3 2020/12/1 2020年度後期 ソフトウェアアーキテクチャ “A Little Java, a Few Patterns”
  2. 2020/12/1 Ch.7 Oh My! 2 表記定義【1】 flat tree split tree

    フラット⽊ スプリット⽊ flat split bud つぼみ フラット スプリット variant バリアント 本⽂中太字で⽰されるプリミティブ値の型・クラスの名前は単数形の表 記にした上でそのまま表⽰する。(booleans → boolean)
  3. 2020/12/1 Ch.7 Oh My! 3 表記定義【2】 クラス名・インターフェース名・プリミティブ値の型名・値:Helvetica Neue Bold サンプル

    クラス名・インターフェース名修飾⼦:Lucida Calligraphy Bold int boolean TreeD Split Flat FruitD bIsFlatV bTreeVisitorI メソッド名:Times New Roman Bold Italic サンプル accept equals コードブロック: ・フォント:Source Code Pro ・テーマ:Androidstudio 右のように表⽰されます。 サンプル 頂いたコメントに基づくメモ
  4. 2020/12/1 Ch.7 Oh My! 5 この章で使う構造 解説等 ピザパイ フルーツの⽊ 今までのおもちゃ

    この章のおもちゃ パイの素材が重なる イメージ 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分⽊
  5. 2020/12/1 Ch.7 Oh My! 6 1 はフラットな TreeD かな? うん、そうだよ。

    Flat Flat Bud 解説等 話者B 話者A 本⽂ p.99 分岐は⼀つも無い
  6. 2020/12/1 Ch.7 Oh My! 7 2 はフラットな TreeD かな? うん、これもフラットな

    TreeD だね。 Flat Bud 解説等 話者B 話者A 本⽂ p.99 分岐は⼀つも無い
  7. 2020/12/1 Ch.7 Oh My! 9 4 いや、これもまたフラットじゃないね。 もう⼀つ例を⽰すよ。 Split Flat

    Bud これはフラットかな? Split Flat Bud Split Bud Bud 解説等 話者B 話者A 本⽂ p.99 分岐がある 分岐がある
  8. 2020/12/1 Ch.7 Oh My! 10 5 フラット⽊とスプリット⽊の違いは⾒つけられたかな。 TreeD に他に何かない限り、よく分かった。 解説等

    話者B 話者A 本⽂ p.99 Fruit Tree Flat Apple Flat Lemon Bud Flat Apple Split Flat Flat Bud Bud Lemon Peach フラット フラットでない 分岐がない 分岐がある
  9. 2020/12/1 Ch.7 Oh My! 11 6 いいね。進もうか。 うん、ぜひ。 話者B 話者A

    本⽂ p.99 フルーツも良いけど ⾦のなる⽊がほしいかな
  10. 2020/12/1 Ch.7 Oh My! 12 7 話者B 話者A いくつかフルーツがあるね。 今まで⾒てきたものと

    ⼤して変わりないね。 全ての TreeD はフラットかスプリットかつぼみである としよう。TreeD の厳密な定義をしようか。 本⽂ p.100
  11. 2020/12/1 Ch.7 Oh My! 13 7 解説等 Fruit Peach equals(o

    : Object) : boolean Apple equals(o : Object) : boolean Pear equals(o : Object) : boolean Lemon equals(o : Object) : boolean Fig equals(o : Object) : boolean 桃 林檎 梨 檸檬 無花果 本⽂ p.100
  12. 2020/12/1 Ch.7 Oh My! 14 7 解説等 Tree Bud Flat

    f : Fruit t : Tree Split l : Tree r : Tree f t l r 本⽂ p.100
  13. 2020/12/1 Ch.7 Oh My! 15 8 解説等 話者A FruitD のバリアントでメソッド

    equals を再定義し た事に気づいた? これはフルーツと他のモノを⽐べる必要が出てく るかもしれないって事だよね。 本⽂ p.100 java.lang.Object の equals をオーバーライドしている。 オリジナルの挙動ではオブジェクトが同⼀の場合に true を返す†。これを拡張し、クラスが同じであれば true を返すように挙動を変更している。 †https://docs.oracle.com/javase/jp/8/docs/api/java/lang/Object.html ⽣成したオブジェクトが特定のフルーツであるかを調 べる必要が出てくることを⽰唆。 new Apple().equals(someObj) 林檎かどうかとか。
  14. 2020/12/1 Ch.7 Oh My! 16 9 解説等 話者B 話者A TreeD

    のバリアントは equals を含んでる? いや、つまりそれらを⽐べる必要が無いって事だね。 だけど、やろうとすればできるよ。 本⽂ p.100 equalsをオーバー ライドしていない。 (equalsはデフォ ルトの挙動:オブ ジェクトが同⼀の 場合に true ) もちろん Fruit の各クラスと同様にする事も出来る が、Tree のクラスについてはクラスが何であるかで 同値性を判定する必要は出てこない事を⽰唆。
  15. 2020/12/1 Ch.7 Oh My! 17 10 話者B 話者A データ型 TreeD

    はこれまで⾒てき たデータ型と何が違うんだろう? 新しいデータ型の名前は Split の バリアントで2回出てくるね。 本⽂ p.101 解説等 第5章:ピザパイ 第7章:フルーツの⽊ ⾃分⾃⾝を2つ含む ⾃分⾃⾝は1つ含む
  16. 2020/12/1 Ch.7 Oh My! 19 11 話者B 話者A メソッドが boolean

    を⽣成するような ビジターのインターフェースを作ろうぜ。 新しいデータ型の定義はこんな感じ。 バリアントを変えようか。 僕達が持ってるものそれぞれに⼀つメ ソッドを追加すれば良いって事だね。 それにしても bTreeVisitorI って変な名前じゃない? 本⽂ p.101
  17. 2020/12/1 Ch.7 Oh My! 20 11 解説等 本⽂ p.101 <<interface>>

    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 ビジターの振る舞いを集約
  18. 2020/12/1 Ch.7 Oh My! 21 12 解説等 話者B 話者A うん、そうだね。変わったインターフェースには変

    わった名前が必要だから、慣れてほしいな。b はビジ ターのメソッドが boolean を返す事を意味しているん だよ。 分かったよ。 本⽂ p.101 <<interface>> bTreeVisitor forBud() : boolean forFlat( f : Fruit, t : Tree ) : boolean forSplit( l : Tree, r : Tree ) : boolean Tree accept( ask : bTreeVisitor ) : boolean accept どれか⼀つ を実⾏ 返り値はビジターのメソッドの返り値となる
  19. 2020/12/1 Ch.7 Oh My! 23 bIsFlat:Flat/Bud だけで構成されてるか判別 解説等 bIsFlatV 分岐がない

    (Split がない) 分岐がある (Split がある) bIsFlatV true false Split
  20. 2020/12/1 Ch.7 Oh My! 24 13 解説等 話者B 話者A bTreeVisitorI

    を実装する事を考えると、bIsFlatV の定義はいくつメソッドを持つだろうか。 TreeD を使って動作し、 TreeD は3つのバリアン トを持っているから3個だね。 本⽂ p.102 accept (Concrete Visitor) bIsFlat 3つ ビジターが訪問する クラスが3種類だから 3種類
  21. 2020/12/1 Ch.7 Oh My! 25 14 解説等 話者B 話者A bIsFlatV

    のメソッドはどの型の値を⽣成するかな。 boolean だよ。 本⽂ p.102 <<interface>> bTreeVisitor forBud() : boolean forFlat( f : Fruit, t : Tree ) : boolean forSplit( l : Tree, r : Tree ) : boolean (Concrete Visitor) bIsFlat
  22. 2020/12/1 Ch.7 Oh My! 26 15 解説等 話者B 話者A bIsFlatV

    を⾒てどの ビジターを思い出す? OnlyOnionsV だ。 本⽂ p.102 OnlyOnionsV true false OnlyOnionsV Top が持ってる素材が Onion だけか 分岐がないか Flat ⽊を構成しているものが Flat だけか (Split が1つも無いか) bIsFlatV true false bIsFlatV
  23. 2020/12/1 Ch.7 Oh My! 27 16 話者B 話者A bIsFlatV の⾻組みはこんな感じかな。

    空⽩を埋めてよ。 今となっては簡単だね。 本⽂ p.102
  24. 2020/12/1 Ch.7 Oh My! 28 16 解説等 本⽂ p.102 Flat

    Split Bud Flat/Bud だけか Split が1つも無いか ⽅針: Split か Bud まで探索を続ける Split が1つでも⾒つかれば false true Bud ⽊の最後まで辿り着いたので Split は⼀つも無かった t Flat Split ではないが, さらに下の⽊ に Split があるかもしれない bIsFlatV ? t l r false Split Split が⾒つかった
  25. 2020/12/1 Ch.7 Oh My! 30 bIsSplit:Split/Bud だけで構成されているか判別 解説等 bIsSplitV フルーツがない

    (Flat がない) bIsSplitV false true Flat Flat フルーツがある (Flat がある)
  26. 話者B 2020/12/1 Ch.7 Oh My! 31 17 解説等 話者A TreeD

    がスプリットとつぼみだけで構成 されているか確認するようなメソッドを 持つ bIsSplitV ビジターを定義してよ。 ここまでは簡単だね。 本⽂ p.102 Split/Bud だけか Flat が1つも無いか ⽅針: Flat か Bud まで探索を続ける Flat が1つでも⾒つかれば false true Bud ⽊の最後まで辿り着いたので Flat は⼀つも無かった t Flat Flat が⾒つかった false
  27. 2020/12/1 Ch.7 Oh My! 32 18 解説等 話者B 話者A 最後の⾏は何が難しいの?

    l と r の両⽅がスプリット⽊かどうか確認しなきゃなら ないんだよね。 本⽂ p.103 Split/Bud だけか Flat が1つも無いか ⽅針: Flat か Bud まで探索を続ける Flat が1つでも⾒つかれば false l r Split Flat ではないがさらに下の⽊に Flat があるかもしれない 調べるべき⽊が2つある r l
  28. 2020/12/1 Ch.7 Oh My! 33 19 解説等 話者B 話者A 簡単じゃないの?

    うん、まぁただ l と r に bIsSplitV のメソッドを使うだ けなんだよね。 本⽂ p.103 Split/Bud だけか Flat が1つも無いか ⽅針: Flat か Bud まで探索を続ける Flat が1つでも⾒つかれば false l r ? Split Flat ではないがさらに下の⽊に Flat があるかもしれない 調べるべき⽊が2つある r ? l bIsSplitV bIsSplitV
  29. 2020/12/1 Ch.7 Oh My! 34 20 解説等 話者B 話者A そして?

    そして両⽅が true であるかを知る必要があるね。 本⽂ p.103 Split/Bud だけか Flat が1つも無いか ⽅針: Flat か Bud まで探索を続ける Flat が1つでも⾒つかれば false l r bIsSplitV ? Split Flat ではないがさらに下の⽊に Flat があるかもしれない 調べるべき⽊が2つある r bIsSplitV ? l 両⽅が true どちらにも Flat はない
  30. 2020/12/1 Ch.7 Oh My! 35 21 解説等 話者B 話者A もし

    が true なら もまた true であると 調べる必要があるかな? うん、だってもし両⽅が true なら スプリット⽊だからね。 本⽂ p.103 Split/Bud だけか Flat が1つも無いか ⽅針: Flat か Bud まで探索を続ける Flat が1つでも⾒つかれば false l r ? Split Flat ではないがさらに下の⽊に Flat があるかもしれない 調べるべき⽊が2つある r true l もし false ならFlat が⼀つでもある bIsSplitV bIsSplitV
  31. 2020/12/1 Ch.7 Oh My! 36 22 解説等 話者B 話者A もし

    が false なら もまた true であると 調べる必要はある? いや、そしたら答えは false だね。 本⽂ p.103 Split/Bud だけか Flat が1つも無いか ⽅針: Flat か Bud まで探索を続ける Flat が1つでも⾒つかれば false l r ? Split Flat ではないがさらに下の⽊に Flat があるかもしれない 調べるべき⽊が2つある r false l もし false なら Flat が⼀つでも ある これ以上調べず とも Flat が既に ⾒つかった! bIsSplitV bIsSplitV
  32. 2020/12/1 Ch.7 Oh My! 37 23 話者B 話者A bIsSplitV の定義を

    を使って完成させようぜ。 今ならできそうだね。 と書き直す事もできる。 † † 本⽂ p.103
  33. 2020/12/1 Ch.7 Oh My! 38 23 解説等 本⽂ p.103 true

    Bud ⽊の最後まで辿り着いたので Flat は⼀つも無かった t Flat Flat が⾒つかった false Flat Split Bud Split/Bud だけか Flat が1つも無いか ⽅針: Flat か Bud まで探索を続ける Flat が1つでも⾒つかれば false l r bIsSplitV ? Split Flat ではないがさらに下の⽊に Flat があるかもしれない 調べるべき⽊が2つある ; 論理積を取る r bIsSplitV ? l and ?
  34. 2020/12/1 Ch.7 Oh My! 39 24 解説等 話者B 話者A bIsSplitV

    のメソッドが true を返すような TreeD の例 を出してみてよ。 つまらない例だけど、こんなのがあるよ。 本⽂ p.104 Flat Split Bud true
  35. 2020/12/1 Ch.7 Oh My! 40 25 解説等 話者B 話者A Split

    を5つ使うような例はどうなるかな。 こんな感じかな。 本⽂ p.104 Flat Split Bud 2: true 3: true 1: true 4: true 5: true 6: true 7: true 8: true 9: true 10: true 11: true
  36. 2020/12/1 Ch.7 Oh My! 42 bHasFruit:Flat が⼀つでも⼊っているかを判別 解説等 bHasFruitV フルーツがない

    (Flat がない) bHasFruitV true true Flat Flat フルーツがある (Flat がある)
  37. 2020/12/1 Ch.7 Oh My! 43 26 解説等 話者B 話者A この

    TreeD はフルーツを⼀つでも持っている? ( → No. 25 ) いや。 本⽂ p.104 Flat Split Bud Fruit は⼀つもぶら下がってない・・・
  38. 話者B 2020/12/1 Ch.7 Oh My! 44 27 話者A bHasFruitV ビジターを定義してみよう。

    こうなるね。 と書き直す事もできる。 † 本⽂ p.104 †
  39. 2020/12/1 Ch.7 Oh My! 45 27 解説等 本⽂ p.104 false

    Bud ⽊の最後まで辿り着いたので Flat は⼀つも無かった t Flat Flat が⾒つかった true Flat Split Bud フルーツがあるか Flat が1つでもあるか ⽅針: Flat か Bud まで探索を続ける Flat が1つでも⾒つかれば true l r ? Split Flat ではないがさらに下の⽊に Flat があるかもしれない 調べるべき⽊が2つある ; 論理和を取る r ? l or ? bHasFruitV bHasFruitV
  40. 2020/12/1 Ch.7 Oh My! 47 28 解説等 話者B 話者A の⾼さは?

    3かな。 本⽂ p.105 Flat Split Bud 3 2 1 0 つぼみは空っぽの状態を表すので⾼さ0
  41. 2020/12/1 Ch.7 Oh My! 51 32 解説等 話者B 話者A TreeD

    の⾼さってなんだろう? ⾃然に⽣えている⽊のように、⽊の⾼さという のは⽊の⽣え際からつぼみの⾼さまででだね。 本⽂ p.105 Flat Split Bud 2 1 0 (⽣え際)
  42. 2020/12/1 Ch.7 Oh My! 52 33 解説等 話者B 話者A iHeightV

    のメソッドは TreeD で動くだろうか? うん、それは int を⽣成するよ。 本⽂ p.105 Flat Split Bud iHeightV 2 : int
  43. 2020/12/1 Ch.7 Oh My! 53 34 解説等 話者B 話者A Height

    の前に付いている i って⼀体何なんだろうね? i は int を表すと思うんだけど、違うかな? 本⽂ p.105 Flat Split Bud 2 : int iHeightV
  44. 2020/12/1 Ch.7 Oh My! 54 35 解説等 話者B 話者A の値は何?

    4だね。 本⽂ p.106 Flat Split Bud 4 3 2 1 0 iHeightV 4
  45. 2020/12/1 Ch.7 Oh My! 55 36 解説等 話者B 話者A なんで⾼さが4なの?

    だって の値が1で の値が3だから 2つのうち⼤きい⽅の数字は3だからね。 本⽂ p.106 4 3 2 1 0 4 1 0 3 2 1 0 1 3 Flat Split Bud iHeightV
  46. 2020/12/1 Ch.7 Oh My! 56 37 解説等 話者B 話者A ⾼さが3から4になるのに何があったの?

    元の⽊が Split によって2つの Tree から構成される Tree だから、数字の⼤きい⽅に⼀つ加えなきゃならな いね。 本⽂ p.106 Flat Split Bud 4 3 2 1 0 4 1 0 3 2 1 0 1 3 3 + 1 iHeightV
  47. 2020/12/1 Ch.7 Oh My! 57 38 解説等 話者B 話者A ⊔

    は x と y のうち⼤きい⽅の数字を取るよ。 おっ、いいね。iHeightV のどんな種類のメソッドを定 義するのかな? 本⽂ p.106 Flat Split Bud 4 3 2 1 0 4 1 0 3 2 1 0 1 3 ⊔ ⼤きい⽅を取る iHeightV
  48. 2020/12/1 Ch.7 Oh My! 58 39 解説等 話者B 話者A iHeightV

    のメソッドは対応する TreeD の⾼さを測定 するよ。 じゃあ、問題点があるね。 本⽂ p.106 Flat Split Bud 4 3 2 1 0 4 1 0 3 2 1 0 1 3 ビジターのメソッドは実 ⾏されたノードをルート とした時の⾼さを返す。 iHeightV
  49. 2020/12/1 Ch.7 Oh My! 59 40 解説等 話者B 話者A なんで?

    boolean を⽣成するようなインターフェースしかこの 章で定義してないよね。 本⽂ p.107 Flat Split Bud iHeightV 4: int 1 0 3 2 1 0 1: int 3: int 2 3 2 1 0 boolean ではなく int を⽣成している
  50. 2020/12/1 Ch.7 Oh My! 60 41 解説等 話者B 話者A だから何?

    iHeightV のメソッドは boolean じゃなくて int を⽣成 するんだよね。 本⽂ p.107 Flat Split Bud 4: int 1 0 3 2 1 0 1: int 3: int 4 3 2 1 0 boolean ではなく int を⽣成している iHeightV
  51. 2020/12/1 Ch.7 Oh My! 61 42 解説等 話者B 話者A 分かった。じゃあ

    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
  52. 2020/12/1 Ch.7 Oh My! 62 43 解説等 話者B 話者A うん、それができたらもう⼀つの

    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
  53. 2020/12/1 Ch.7 Oh My! 63 44 解説等 話者B 話者A 消費する型が違いさえすれば同じクラスに同じ名前の2

    つのメソッドを持つことが出来るよ。 bTreeVisitorI はたしかに iTreeVisitorI と違うから、2種 類の accept を TreeD に持てるんだね。 本⽂ p.107 Tree accept bTreeVisitor iTreeVisitor bTreeVisitorだ iTreeVisitorだ
  54. 2020/12/1 Ch.7 Oh My! 64 45 解説等 話者B 話者A TreeD

    のバリアントに新しい 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⽤ を実⾏
  55. 2020/12/1 Ch.7 Oh My! 65 46 話者B 話者A 他のも簡単だよ。accept を複製しよう。

    accept が消費する型と⽣成する型も 変える必要があるね。 本⽂ p.108
  56. 2020/12/1 Ch.7 Oh My! 66 46 解説等 本⽂ p.108 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 Flat⽤ を実⾏ Flat f : Fruit t : Tree Split l : Tree r : Tree Flat⽤ を実⾏ Split⽤ を実⾏ Split⽤ を実⾏
  57. 2020/12/1 Ch.7 Oh My! 67 47 話者B 話者A これが iHeightV

    だよ。 今となっては簡単だね。 これらのメソッドを完成させよう。 ⊔ 本⽂ p.108
  58. 2020/12/1 Ch.7 Oh My! 68 47 解説等 Flat Split Bud

    ⽅針: ⾃分をルートとした時の⾼さに1 を加えたものを下の階層に伝える 0 Bud ⾃分より上の階層はない よって⾼さは0 t Flat 上の階層の⽊が1つ存在 その⾼さを調べてもらい1⾜す iHeightV ? + 1 t l r iHeightV ? Split 上の階層の⽊が2つ存在 それぞれ⾼さを調べてもらい⼤きい⽅に1⾜す 本⽂ p.108 下の階層へ 下の階層へ l r iHeightV ? ? + 1 max 下の階層へ
  59. 2020/12/1 Ch.7 Oh My! 69 48 解説等 話者B 話者A の値は何?

    もちろん、1だよ。 本⽂ p.108 Flat Split Bud ルート iHeightV 1
  60. 2020/12/1 Ch.7 Oh My! 70 49 解説等 話者B 話者A なんで1なの?

    だって が0で、0と0のうち⼤きい⽅が0で、さらに進む と1だからだね。 本⽂ p.108 Flat Split Bud 1 1: 0 2: 0 3: max(0, 0) + 1 = 0 + 1 = 1 iHeightV
  61. 2020/12/1 Ch.7 Oh My! 72 50 話者B 話者A の値は何? もし

    tSubstV ビジターが梨を林檎に変えるなら、 これが僕達が得られるものだよ。 本⽂ p.109
  62. 2020/12/1 Ch.7 Oh My! 73 50 解説等 ⾷べたい。 本⽂ p.109

    TreeD ⽞師 Flat Split Bud tSubstV ( , ) ビジター適⽤前 ビジター適⽤後
  63. 2020/12/1 Ch.7 Oh My! 74 51 解説等 話者B 話者A 正解。tSubstV

    ビジターを定義しようか。 第5章の終わりの SubstFishV や SubstIntV みたいだ けど、まだできないよ。 本⽂ p.109 SubstFishV ( , ) SubstIntV ( , )
  64. 2020/12/1 Ch.7 Oh My! 75 52 解説等 話者B 話者A 障害は何だろう?

    そのメソッドは 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
  65. 2020/12/1 Ch.7 Oh My! 76 53 解説等 話者B 話者A よくやった。データ型

    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
  66. 2020/12/1 Ch.7 Oh My! 78 54 解説等 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 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
  67. 2020/12/1 Ch.7 Oh My! 79 55 話者B 話者A じゃあ tSubstV

    を定義しようか。 これも簡単さ。2つのフィールドを持ってい て⼀つは新しい Fruit のためのもの、もう⼀ つは古い Fruit のためのもの、そして残りは 単純だね。 本⽂ p.111
  68. 2020/12/1 Ch.7 Oh My! 80 55 解説等 本⽂ p.111 <<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 <<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
  69. 2020/12/1 Ch.7 Oh My! 81 55 解説等 本⽂ p.111 Flat

    Split Bud ⽅針: Flat を⾒つけ、持っているフルー ツが置換対象だったら置換 Bud ⾃分より上の階層はない ただ Bud を返す。 t Flat ぶら下がってるフルーツが 置換対象だったら置換 さらに上の階層に置換を適⽤ l r tSubstV Split 上の階層の⽊が2つ存在 さらに上の階層の2つの⽊に置換を適⽤ 下の階層へ 下の階層へ tSubstV 下の階層へ t' tSubstV l' r'
  70. 2020/12/1 Ch.7 Oh My! 83 56 話者B 話者A これは3つの Fig

    を持っている TreeD だよ。 ある FruitD の出現回数を数え上げるようなメソッド をもつ iOccursV をどのように定義するだろう? ビジターでさえももう⾯⽩くないなぁ。 本⽂ p.111
  71. 2020/12/1 Ch.7 Oh My! 84 55 解説等 本⽂ p.111 <<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 <<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
  72. 2020/12/1 Ch.7 Oh My! 85 55 解説等 本⽂ p.111 Flat

    Split Bud ⽅針: Flat を⾒つけ、持っているフルー ツがカウント対象だったら⾃分よ り上の階層に1を⾜す Bud ⾃分より上の階層はない フルーツはないので0。 t Flat 上の階層のカウント結果に ぶら下がってるフルーツが カウント対象だったら+ 1する l r iOccursV Split 上の階層の⽊が2つ存在 さらに上の階層の2つの⽊のカウント結果を⾜す 下の階層へ 下の階層へ iOccursV 下の階層へ iOccursV 0 t ? + 1 + 0 ? ? +
  73. 2020/12/1 Ch.7 Oh My! 86 57 解説等 話者B 話者A フルーツを⼊れたヨーグルトは好き?

    ココナツシャーベットが好きなんだけど。 本⽂ p.112
  74. 2020/12/1 Ch.7 Oh My! 88 58 解説等 話者B 話者A TreeD

    とそのバリアントにほぼ同⼀の種類の 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
  75. 2020/12/1 Ch.7 Oh My! 90 59 解説等 話者B 話者A なんとかできないかな?

    もし boolean と int がクラスだったら、boolean、 int、TreeD に Object を使う事が出来るよね。だけ ど、残念ながらそうじゃない。 本⽂ p.112 boolean int Tree java.lang.Object bTreeVisitorI iTreeVisitorI tTreeVisitorI TreeVisitorI ? プリミティブ型
  76. Boolean boolean 2020/12/1 Ch.7 Oh My! 91 60 解説等 話者B

    話者A Integer と Boolean を思い出して。 これだったらできるよ。 そっか、そうだったね。Boolean は boolean に関係し ているクラスで、Integer は int に関係しているクラス だ。 本⽂ p.112 Tree java.lang.Object bTreeVisitorI iTreeVisitorI tTreeVisitorI TreeVisitorI プリミティブ型ラッパークラス Integer int
  77. 2020/12/1 Ch.7 Oh My! 92 61 話者B 話者A これは boolean、int、TreeD

    の場所に Object を指定した TreeD だよ。 Bud のバリアントとデータ型だよ。 TreeD の残りのバリアントを定義してみて。 こんな感じかな。 本⽂ p.112
  78. 2020/12/1 Ch.7 Oh My! 93 61 解説等 Tree accept( ask

    : 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
  79. 2020/12/1 Ch.7 Oh My! 94 62 話者B 話者A いいね。じゃあ bIsFlatV

    の Object版の IsFlatV を定義してみようか。 たいしたことないね。 本⽂ p.113
  80. 2020/12/1 Ch.7 Oh My! 95 63 解説等 話者B 話者A IsSplitV

    はどうかな? ちょっと違うね。この場合、元のバージョンで l.accept(this) によって⽣成された Boolean の中⾝ の boolean の値を決定する⽅法が必要だね。 本⽂ p.113 旧 l.accept(this), r.accept(this) は Object であり boolean ではない。 l.accept(this) Boolean boolean java.lang.Object boolean 値を取り出す 必要がある
  81. † もしJavaがメソッドに対してパラメトリックな多相性を持っていれ ば我々のビジターにダウンワードキャストは必要なかったでしょう。 (Martin Odersky, Philip Wadler, “Pizza into Java:

    Translating Theory into Practice,” Conference Record on Principles on Programming Languages, pp.146-159, パリ, 1997年.) 2020/12/1 Ch.7 Oh My! 96 64 話者B 話者A こんな感じだね。 ああ、l.accept(this) が Object を⽣成するから、まず それを Boolean に変換する†必要があるんだ。そした らその中⾝の値を booleanValue メソッドで決定でき るんだね。第5章で Object を OneMoreThan に変換 したときにも⾒たね。 ※ 総称型は J2SE 5.0 (2004年) で導⼊;当時は使えな かった。 https://ja.wikipedia.org/wiki/Java%E3%83%90%E3 %83%BC%E3%82%B8%E3%83%A7%E3%83%B3 %E5%B1%A5%E6%AD%B4 本⽂ p.113
  82. 2020/12/1 Ch.7 Oh My! 97 64 解説等 l.accept(this) java.lang.Object (Boolean)

    l.accept(this) Boolean boolean ダウンワードキャスト ((Boolean) l.accept(this)) Boolean boolean boolean .booleanValue() 値の取り出し 本⽂ p.113
  83. 2020/12/1 Ch.7 Oh My! 98 65 解説等 話者B 話者A 変換はいつでも使える?

    うん、だって l.accept(this) によって⽣成される Object はいつも Boolean だからね。 本⽂ p.113 accpet するのは⾃分⾃⾝であり、全てのメソッドで Boolean を返しているため常にダウンワードキャ ストは成功する。
  84. 2020/12/1 Ch.7 Oh My! 102 Tree / TreeVisitor • ビジターに総称型を使⽤。

    • Tree にビジターを accept する際にはそのビジターがどんな型の値をやりとりするか知らなくて済む ように、値のやりとりをビジター内に閉じ込めた。(resultStore という名前のスタックでやりとり)