インターフェイス実装の活用例 as編
TRANSCRIPT
インターフェイス実装の活用例ActionScript編
Aiming大阪スタジオ
ソフトウェアエンジニア 松田理孝
2012/12/12
Yoshitaka Matsuda
– Aiming大阪スタジオ
– 新入社員、1年目
– C# → ActionScript
• 大阪では異例の経歴
– 趣味はイラスト描き →
突然ですが
• for(..) { switch(..) { case.. case.. case.. } }
– っていうソースコード
うっかり、書いちゃったりしますか– 行数多い
– 見た目が悪い
– よくわからん
• 綺麗にしたい!!
→インターフェイス使えば解決できる
インターフェイス
• 英語で界面や接触面、中間面などといった意味を持ち、転じてコンピュータと周辺機器の接続部分を表すようになった。(出典:Wikipedia)
• ユーザインターフェイスとか
• 電気のコンセントとかUSBとか
プログラムのインターフェイス
• 内部はわからない
• 振る舞いはわかる
→とある型の引数を取って、とある型を返す
→引数の数も当然一緒
→名前も一緒じゃないといけない
• そこまで一緒なら、継承・オーバーライドでよくね?
家電に例える
どちらも食品を入れられる何か
→でも実際、動作は全く別物!!
クラスの継承とはどういうことか
1. 食べ物を入れる箱(空間)を用意する
2. 箱に扉の機能を追加する
3. さらに冷やす機能追加して冷蔵庫にする
4. 上の箱に温める機能を追加してレンジ
→箱とドアは、レンジと冷蔵庫で共有している
クラスの継承とはどういうことか
• 冷蔵庫は扉、両開きがいいです
– 扉クラスに両開きかどうか判定させる?
– 両開き扉クラスを作る?
• 冷蔵庫の箱にはペットボトル入れられます
– レンジに入れられないものとかどうしよう?
– 箱の内部で逐一判定?
→スパゲティコード化
インターフェイスにすると?
• インターフェイスの用意
– モノを出し入れできる扉インターフェイス
→扉を介して、入れたり出したりする振る舞いは
冷蔵庫でもレンジでも一緒である
→実際、両開きかどうかは実装に任せる
– 冷蔵庫は両開き実装
– レンジは片開き実装
外部から見たら
• 扉インターフェイスがある
→これを介せばモノが出し入れできるんだろう
• 詳細はよくわからないけど、出し入れできるという振る舞いはわかる
実際に定義してみる
• 等価比較の振る舞いをする
実装してみる
• 内部がintだけのダミークラス
– このクラスだけの等価比較の実装
使ってみる
• 当然、こうなる
• あ、やっぱDummyとintでもtrueにしたい!– Dummyのequalsを変えるだけでいい
→ほかに影響は出ない!!
Tupleの等価比較
• 一時的に、値をセットにしたい時に使う
– 型とか自由、単にペアやトリオにしたいだけ
– 2変数のタプル作ってみる
Tupleの等価比較
• IEquals.equalsの実装
– 各要素がIEqualsを実装していれば、そちら優先
→要素の実際の型が分からなくても比較できる!
for-switchのパターン
• ゲームのスキルを考える
– 使用できる場所を制限したい場合を考える
• バトルで使えるか
• フィールドで使えるか
→とりあえず、Switch文で場合分けしてみる
for-switchのパターン
• Scene.Townが増えたらどうなるの?
• アイテムとか増えたらどうなるの?
for-switch撲滅する
→まずインターフェイスを用意
– 使用できるかの判定関数
– 実際使用したときの処理
を定義する(実装はしない)
for-switch撲滅する
– 実際に判定を行う処理を実装
• Usable.OnField
• Usable.OnBattle
for-switch撲滅する
Itemにも実装しちゃう
for-switch撲滅する
– itemも同じくitem.isUsable(..)で判定できる
• ソースコードの重複なども無くすことができる
Usable.OnFieldが呼ばれる
何が嬉しいか
• ItemやSkillで判定式を共有できる– Usable.OnField、Usable.OnBattle
• 判定式の追加が容易– Usable.OnTownなど、後から追加できる
– 他の部分に変更を出さない
• 無駄なswitch文、if文を極力なくせる– 実際のインスタンスを入れ替えている
• if文の判定を間違えることがない– バグが起きにくい
インターフェイスを使うに当たって
• インターフェイスはオブジェクトの関数・プロパティを定義するヘッダーファイルではない
– ISampleがSampleだけに使われる想定があってはならない
• インターフェイスは具体的でなくていい
– 1つのインターフェイスにメソッドがたくさん定義されるような状態であれば、分離すること
さいごに
• とにかく継承はできる限りやめましょう
• クラスは疎結合にしましょう
– 仕様変更に耐えられるように
– 仕様追加に耐えられるように
– あとから参加した人が見やすいように
– 機能を小分けしてチーム開発しやすいように
• 「ここの処理、変更してほしいんですけど」– 変更部分のみを修正すれば、周りに影響が出ない!
» ってのが理想……