継承よりもコンポジション(1)
2009/01/30 20:40 - AS3.0
オブジェクト指向の三大要素の一つに「継承」というものがありますね。
この継承というのはクラス拡張のための手段であるというのは皆さんご案内のことと思いますが、実はクラス拡張には継承よりもパワフルな「コンポジション」というテクニックがあるということを「詳説 ActionScript 3.0」を読んで知り、非常に衝撃を受けたというのが今回の話。
皆さん知ってました? コンポジションって。ワタクシ初めて知りました。 インターフェイスに引き続き、また私の無知が露呈してしまいましたですよ。
ずいぶん前にちょこっと手をつけて、今は絶賛放置中のドット・タイポシリーズというのがあります。 このとき文字列をドット化するエンジンの汎用化について考えていました。
文字列をドット化するには、TextField を BitmapData に draw して、その BitmapData を1ピクセルずつ getPixel で走査するという手順を踏むわけですが、ということはこのエンジン、画像ファイルをドット化したいと思ったときも、そのまま使えるんじゃないかなぁ、ということに思い至りました。
で、設計に入ったわけですが、ドット化するメソッドの引数に文字列なり画像ファイルなりを指定するようにしたいものである、というのがまず大前提としてありました。
以下のような感じ。
一つのドット化エンジンクラスを作って、むりやりオーバーロードで対応するという考え方もあるでしょう。
でも同じドット化という行動でも、文字列と画像ファイルでは、そこそこ異なる部分が出てきそうな予感。 だったら文字列をドット化する TextPixelizer と画像をドット化する ImagePixelizer という二つのクラスに分けよう、という結論に達しました。
なら継承だな、ってんで、ImagePixelizer をスーパークラス、TextPixelizer をサブクラスとして設計してみました。
BitmapData をスキャンするメソッド pixelize は ImagePixelizer 内に記述します。
TextPixelizer では TextField を作ってそれを BitmapData に draw、その BitmapData をスキャンする部分はスーパークラスに記述済みの pixelize という寸法。
これでよかろう、と思っていたら問題発生!
上が画像をドット化する場合で、下が文字列をドット化する場合なんですが、引数の型が異なるからオーバーライドできないじゃんか…… ってことは継承が使えない、ってゆーか最初にオーバーロードするしないを検討したじゃんかよ!
バカよあんたバカなんだわ、と自分に毒づく日々でしたあの本に出会ったのは。
そう「詳説 ActionScript 3.0」に。
この本のP128~130に、クラスを拡張する手段として継承の他に「コンポジション」という名のテクニックが存在するということが書いてあったのです。
今ここに一筋の光明が射した!
続く。