Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
オブジェクト指向入門 パラメータ多相 実装継承 nrs @nrslib
Slide 2
Slide 2 text
パラメータ多相
Slide 3
Slide 3 text
パラメータ = ?
Slide 4
Slide 4 text
ArrayList
Slide 5
Slide 5 text
ArrayList キャストすれば計算はできる
Slide 6
Slide 6 text
ArrayList 実行時エラー もし文字列を代入したら?
Slide 7
Slide 7 text
ArrayList 実行時エラー
Slide 8
Slide 8 text
ArrayList
Slide 9
Slide 9 text
ArrayList 型を意識する必要が出てしまう
Slide 10
Slide 10 text
問題点 ? =
Slide 11
Slide 11 text
問題点 キャスト =
Slide 12
Slide 12 text
キャストをするということは 問題点 キャスト =
Slide 13
Slide 13 text
キャストをするということは list 変数には 数字しか入らないという 暗黙的なルールがある 問題点 キャスト =
Slide 14
Slide 14 text
キャストをするということは 暗黙的なルール = ランタイムエラーの原因 list 変数には 数字しか入らないという 暗黙的なルールがある 問題点 キャスト =
Slide 15
Slide 15 text
どうすれば解決できるのか
Slide 16
Slide 16 text
どうすれば解決できるのか ランタイムエラーではなく コンパイルエラーにする
Slide 17
Slide 17 text
どうすれば解決できるのか ランタイムエラーではなく コンパイルエラーにする ジェネリクス(総称型)
Slide 18
Slide 18 text
List int 型の List と宣言
Slide 19
Slide 19 text
List int 型の List と宣言 int 型は要素として追加できる
Slide 20
Slide 20 text
List int 型の List と宣言 int 型は要素として追加できる int 型の List の要素なので int 型 (キャスト不要!)
Slide 21
Slide 21 text
List int 型以外の要素追加は コンパイルエラー
Slide 22
Slide 22 text
パラメータ = ?
Slide 23
Slide 23 text
パラメータ = ?
Slide 24
Slide 24 text
パラメータ = 型
Slide 25
Slide 25 text
パラメータ = 型 パラメータ多相は型情報を抽象化する 型を抽象化して捉えることで 特定の型に捉われない実装を行える
Slide 26
Slide 26 text
エクササイズ
Slide 27
Slide 27 text
お題はエラーコード
Slide 28
Slide 28 text
エラーコード
Slide 29
Slide 29 text
エラーコード エラーコードってどう扱っていますか 形式は数字ですか? 文字列ですか? 粒度はどれくらいですか?
Slide 30
Slide 30 text
エラーコード 形式は列挙体で 粒度はユースケース毎 にしようと思いました
Slide 31
Slide 31 text
エラーコード
Slide 32
Slide 32 text
エラーコード
Slide 33
Slide 33 text
エラーコード ユースケース毎に起こりうるエラーがわかる
Slide 34
Slide 34 text
エラーコード ユースケース毎に起こりうるエラーがわかる -> エラーコードからの該当箇所特定が容易
Slide 35
Slide 35 text
レスポンス どんなクラスを作る?
Slide 36
Slide 36 text
レスポンス
Slide 37
Slide 37 text
レスポンス
Slide 38
Slide 38 text
レスポンス
Slide 39
Slide 39 text
レスポンス
Slide 40
Slide 40 text
レスポンス 似たようなコードが多いので スーパークラスを作ります
Slide 41
Slide 41 text
スーパークラス
Slide 42
Slide 42 text
スーパークラス
Slide 43
Slide 43 text
スーパークラス
Slide 44
Slide 44 text
スーパークラス
Slide 45
Slide 45 text
使ってみよう
Slide 46
Slide 46 text
使ってみよう
Slide 47
Slide 47 text
使ってみよう
Slide 48
Slide 48 text
使ってみよう もしエラーコードで メッセージを出し分けしたかったら?
Slide 49
Slide 49 text
エラーコードでメッセージを出し分け
Slide 50
Slide 50 text
エラーコードでメッセージを出し分け イマイチポイント① キャスト
Slide 51
Slide 51 text
エラーコードでメッセージを出し分け キャスト 実際のクラスを知っている = イマイチポイント① キャスト
Slide 52
Slide 52 text
エラーコードでメッセージを出し分け イマイチポイント② 他のレスポンスでも 似たようなロジックを 書くことになりそう
Slide 53
Slide 53 text
目標はこんな感じ
Slide 54
Slide 54 text
実装してみよう 目標はこんな感じ
Slide 55
Slide 55 text
まずはキャスト撲滅
Slide 56
Slide 56 text
object を使っているところを
Slide 57
Slide 57 text
ジェネリクスに
Slide 58
Slide 58 text
ジェネリクスに
Slide 59
Slide 59 text
レスポンスが変更されます
Slide 60
Slide 60 text
レスポンスが変更されます
Slide 61
Slide 61 text
キャスト消失
Slide 62
Slide 62 text
キャスト消失
Slide 63
Slide 63 text
次はここ
Slide 64
Slide 64 text
一旦の目標
Slide 65
Slide 65 text
エラーメッセージに変換するモジュール
Slide 66
Slide 66 text
エラーメッセージに変換するモジュール Q. 他のエラーコードにも対応させたら?
Slide 67
Slide 67 text
No content
Slide 68
Slide 68 text
イマイチポイント 型確認
Slide 69
Slide 69 text
イマイチポイント キャスト イマイチポイント 型確認
Slide 70
Slide 70 text
イマイチポイント キャスト イマイチポイント 型確認 イマイチポイント どんどん増える
Slide 71
Slide 71 text
イマイチポイント キャスト イマイチポイント 型確認 イマイチポイント どんどん増える 総評 イマイチ
Slide 72
Slide 72 text
そもそもエラーコードに対応する メッセージはどこに書くべきか
Slide 73
Slide 73 text
エラーコードに書きたい
Slide 74
Slide 74 text
エラーコードに書きたい ※多言語化するときはメッセージIDです
Slide 75
Slide 75 text
エラーコードからエラーメッセージを設定する
Slide 76
Slide 76 text
エラーコードからエラーメッセージを設定する
Slide 77
Slide 77 text
エラーコードからエラーメッセージを取得する
Slide 78
Slide 78 text
エラーコードからエラーメッセージを取得する {UserPostErrorCode.IllegalCharactorOnUserName, ErrorMessageAttribute(“ユーザ名に利用できない文字が存在しています”)}, {UserPostErrorCode.DuplicatedUserName, ErrorMessageAttribute(“ユーザー名が重複しています”)} という連想配列を作ってる
Slide 79
Slide 79 text
モジュール化してみる
Slide 80
Slide 80 text
モジュール化してみる
Slide 81
Slide 81 text
モジュール化してみる これを使うとこうなる
Slide 82
Slide 82 text
モジュール化してみる オートボクシング発生
Slide 83
Slide 83 text
オートボクシングを防ぐには
Slide 84
Slide 84 text
オートボクシングを防ぐには object を使わなければいい
Slide 85
Slide 85 text
オートボクシングを防ぐには object を使わなければいい ジェネリクス
Slide 86
Slide 86 text
No content
Slide 87
Slide 87 text
めでたしめでたし…
Slide 88
Slide 88 text
と思いきや
Slide 89
Slide 89 text
使ってみると
Slide 90
Slide 90 text
使ってみると 型を書かなくてはいけない
Slide 91
Slide 91 text
使ってみると 型を書かなくてはいけない 型は大事だけど 型を意識する役目はコンパイラ
Slide 92
Slide 92 text
型を書かなくてもいいように 改良しよう
Slide 93
Slide 93 text
まずは少しでもタイプセーフにするために マークアップインターフェースを用意 (object で扱えばいいので必須ではないです)
Slide 94
Slide 94 text
メッセージ取得部分をクラスに
Slide 95
Slide 95 text
作ったクラスを利用する
Slide 96
Slide 96 text
出来上がった最終形
Slide 97
Slide 97 text
型を意識しないようにすると
Slide 98
Slide 98 text
最終形は?
Slide 99
Slide 99 text
拡張メソッドで
Slide 100
Slide 100 text
拡張メソッドで 拡張メソッドは乱用不可 継承でも実現できる 拡張メソッドを採用する理由は要検討
Slide 101
Slide 101 text
拡張メソッドで 拡張メソッドは乱用不可 継承でも実現できる 拡張メソッドを採用する理由は要検討 今回の採用理由は メッセージ処理はプレゼンテーション層の処理 Response というオブジェクトが担保すべきでない
Slide 102
Slide 102 text
ジェネリクスの制約について
Slide 103
Slide 103 text
制約 型パラメータに条件を付ける機能
Slide 104
Slide 104 text
制約
Slide 105
Slide 105 text
制約 Response のメソッド 呼びたいけど
Slide 106
Slide 106 text
制約 Response のメソッド 呼びたいけど 型がわからない
Slide 107
Slide 107 text
制約 TResponse は Response か Response のサブタイプである と定義
Slide 108
Slide 108 text
制約 TResponse は Response か Response のサブタイプである と定義 ToErrorMessage() が呼べる
Slide 109
Slide 109 text
共変 / 反変
Slide 110
Slide 110 text
共変 / 反変 頭がこんがらがるので省略
Slide 111
Slide 111 text
共変 / 反変 頭がこんがらがるので省略 in 修飾子 out 修飾子 こういうことを可能にします
Slide 112
Slide 112 text
ジェネリクスまとめ 本来やりたいことは object で実現できる でも型の恩恵は受けたいので型を抽象化した
Slide 113
Slide 113 text
実装継承の話をします
Slide 114
Slide 114 text
継承は
Slide 115
Slide 115 text
継承は ポリモーフィズムを 実現するための機能である
Slide 116
Slide 116 text
継承は ポリモーフィズムを 実現するための機能である
Slide 117
Slide 117 text
継承は コードの共通化を 実現するための機能である
Slide 118
Slide 118 text
なぜこれを強調するのか
Slide 119
Slide 119 text
継承はとても難しいから なぜこれを強調するのか
Slide 120
Slide 120 text
継承の難しさ
Slide 121
Slide 121 text
継承の難しさ
Slide 122
Slide 122 text
継承の難しさ
Slide 123
Slide 123 text
継承の難しさ
Slide 124
Slide 124 text
継承の難しさ 継承構造は利用者次第 作成者が関与できない
Slide 125
Slide 125 text
No content
Slide 126
Slide 126 text
No content
Slide 127
Slide 127 text
No content
Slide 128
Slide 128 text
メソッドを override するかしないか
Slide 129
Slide 129 text
メソッドを override するかしないか これは形を変えた条件分岐
Slide 130
Slide 130 text
合わさるとやばい
Slide 131
Slide 131 text
サブタイプのための継承が行われる
Slide 132
Slide 132 text
サブタイプのための継承が行われる
Slide 133
Slide 133 text
サブタイプのための継承が行われる
Slide 134
Slide 134 text
サブタイプのための継承が行われる スーパークラスで 利用されていない
Slide 135
Slide 135 text
サブタイプのための継承が行われる スーパークラスで 利用されていない 共通化すべき処理が 発見されたとき もう継承できない
Slide 136
Slide 136 text
こんな感じがおすすめ
Slide 137
Slide 137 text
こんな感じがおすすめ
Slide 138
Slide 138 text
こんな感じがおすすめ 共通化する目的は 改修する時に変更箇所を集約することが目的 書く時に楽をするためだけの継承はしてはいけない
Slide 139
Slide 139 text
もはやそれは別物だよ
Slide 140
Slide 140 text
もはやそれは別物だよ
Slide 141
Slide 141 text
もはやそれは別物だよ is-a 関係の難しさ
Slide 142
Slide 142 text
まとめ 結果として出来上がる継承構造の形成に関して スーパークラスの製作者が制御する仕組みがない オーバーライドできるメソッドの数により複雑さが増す サブタイプのための継承が可能だが 本来の目的から反する クラスハックのための継承が行われることがあり 驚き最小の原則に反する
Slide 143
Slide 143 text
継承の怖さについて学んだところで 継承をしてみよう
Slide 144
Slide 144 text
No content
Slide 145
Slide 145 text
まずは 重複していないところを チェック
Slide 146
Slide 146 text
No content
Slide 147
Slide 147 text
No content
Slide 148
Slide 148 text
No content
Slide 149
Slide 149 text
継承方針を決める
Slide 150
Slide 150 text
継承方針を決める スーパークラスは何か
Slide 151
Slide 151 text
継承方針を決める スーパークラスは何か 「ファイルを出力するコマンド」
Slide 152
Slide 152 text
No content
Slide 153
Slide 153 text
この部分は virtual メソッドで用意する?
Slide 154
Slide 154 text
もし用意したらどうなる?
Slide 155
Slide 155 text
たぶんこうなる
Slide 156
Slide 156 text
この部分は virtual メソッドで用意する?
Slide 157
Slide 157 text
この部分は virtual メソッドで用意する? → No! 振る舞いがないのでパラメータで十分
Slide 158
Slide 158 text
No content
Slide 159
Slide 159 text
この部分は virtual メソッドで用意する?
Slide 160
Slide 160 text
この部分は virtual メソッドで用意する? → Yes ! 振る舞いがあるので override 必要
Slide 161
Slide 161 text
スーパークラス
Slide 162
Slide 162 text
スーパークラス パラメータで受け取り
Slide 163
Slide 163 text
スーパークラス 振る舞いは変更可能
Slide 164
Slide 164 text
継承すると
Slide 165
Slide 165 text
継承すると
Slide 166
Slide 166 text
継承すると
Slide 167
Slide 167 text
継承すると 差分に集中できる
Slide 168
Slide 168 text
よりよいスーパークラス
Slide 169
Slide 169 text
よりよいスーパークラス 現在のインターフェース
Slide 170
Slide 170 text
よりよいスーパークラス 必ず実装してほしい 現在のインターフェース
Slide 171
Slide 171 text
よりよいスーパークラス
Slide 172
Slide 172 text
よりよいスーパークラス
Slide 173
Slide 173 text
よりよいスーパークラス 仮実装不要
Slide 174
Slide 174 text
よりよいスーパークラス インターフェース
Slide 175
Slide 175 text
よりよいスーパークラス インターフェース
Slide 176
Slide 176 text
よりよいスーパークラス インターフェース 継承前提のクラスだと わかる
Slide 177
Slide 177 text
よりよいスーパークラス インターフェース 実装しないと コンパイルエラー 継承前提のクラスだと わかる
Slide 178
Slide 178 text
実は継承を使わずに 同様のことを実現ができます
Slide 179
Slide 179 text
No content
Slide 180
Slide 180 text
関数を引数で受け取る
Slide 181
Slide 181 text
利用イメージ
Slide 182
Slide 182 text
利用イメージ
Slide 183
Slide 183 text
継承するかしないか
Slide 184
Slide 184 text
継承するかしないか 継承 Ver. 関数 Ver.
Slide 185
Slide 185 text
継承するかしないか 継承 Ver. 関数 Ver. 重複!
Slide 186
Slide 186 text
継承するかしないか 継承したクラス自体を 再利用するとき継承する 継承 Ver. 関数 Ver.
Slide 187
Slide 187 text
関数を受け取るクラスの継承
Slide 188
Slide 188 text
関数を受け取るクラスの継承
Slide 189
Slide 189 text
override されるメソッドについて 簡単なガイドライン
Slide 190
Slide 190 text
範囲を小さく 初期化処理に サブクラスで追加処理したい
Slide 191
Slide 191 text
範囲を小さく
Slide 192
Slide 192 text
範囲を小さく
Slide 193
Slide 193 text
範囲を小さく super.Initialize()を 呼ばないと スーパークラスの初期化が発生しない
Slide 194
Slide 194 text
範囲を小さく super.Initialize()を 呼ばないと スーパークラスの初期化が発生しない =スーパークラスの破壊が可能
Slide 195
Slide 195 text
範囲を小さく
Slide 196
Slide 196 text
スーパークラスの 初期化を担保している 範囲を小さく
Slide 197
Slide 197 text
ネーミング
Slide 198
Slide 198 text
ネーミング 初期化処理の前 初期化処理の後
Slide 199
Slide 199 text
ネーミング 初期化処理の前 初期化処理の後 Hook するメソッドが処理の最初か最後かは 重要な要素であったりするので 現在進行形と過去形で使い分ける
Slide 200
Slide 200 text
実装継承まとめ 処理の共通化が目的 共通化することで改修する時の変更箇所を集約する 振る舞いがあるかどうかは継承をするかの大事な判断基準
Slide 201
Slide 201 text
Auther nrs HomePage https://nrslib.com Twitter @nrslib