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