多重継承の例

Mopsにおける多重継承を「はろーわーるど」でも使ったstaticTextクラスのソースを見ながら紹介したいと思います。

staticTextクラスはSelection Frameworkに含まれているウインドウアイテムのクラスです。


[ここからリスト]

\ 28Oct94 dbh updated to 2.5 syntax

(*

StaticText, or non-editable text in the sense that it is not TextEdit text,
is text that is meant for display only. StaticText remembers everything it
needs to draw itself including the position in the window, the font, fontsize,
etc. StaticText is also a selection class so it will follow our standard
protocol. A maximum of 16 characters will fit in a StaticText object.

Note the heavy reliance on multiple inheritance.

*)

need $16
need font
need point+
need nullselect

:class staticText super{ $16 font point+ nullselect }

  :m classinit:
    " Static Text" put: super> $16
    50 50 moveto: super> point+
  ;m
  
  :m new: ( wptr -- )
    drop
    getnew: super> font
  ;m
  
  :m draw:
    get: super> point+ MoveTo    \ move graphics pen with MoveTo
    set: super> font        \ must always set: the font before
                    \ drawing because we have no idea
                    \ what the current graphport
                    \ settings are
    get: super> $16 mDrawString
  ;m
  
  :m erase:              \ simply erases the screen display,
                    \ does not change the string itself
    get: mode            \ font ivar data, save on stack
                    \ for subsequent restore
    konst srcBic put: mode
    draw: self
    put: mode            \ restore mode
  ;m

;class

endload


[ここまで]

ご覧のようにじつはstaticTextクラス自身はインスタンス変数を持っていません。

$16 font point+ nullselect

という優先順位で多重継承をおこなっており、staticTextクラスがオーバーライドしているメソッド以外のメッセージはまず優先順位の高い$16というクラスに渡されます。

$16というクラスは16バイト固定長の文字列を扱うクラスです。$16クラスが理解できないメッセージは次にフォント全般を扱うfontクラスに渡されます。同様にメッセージは座標を表わすpoint+クラス、ウインドウアイテムに共通に必要とされるプロトコルを定めたnullselectクラスへと次々に渡されます。

このように多重継承しているクラス間の優先順位によってメッセージの流れは自然に決まるためメソッド名の衝突を防ぐための特別な工夫は必要ありません。
メソッドをオーバーライドしてsuper>というワードを使用すれば優先順位とは違うメッセージの流れをつくることもできます。

単純継承でインスタンス変数としてこれらのクラスの機能を実装しようとすると、まず$16クラスを継承したいところですがウインドウアイテムに共通のプロトコルを定めたnullselectクラスを継承する必要もあり、どちらを継承するかという悩みにぶつかります。
普通は泣く泣く共通のプロトコルを定めたnullselectクラスからサブクラス化(派生)し残りの機能はインスタンス変数として取り込んでメッセージをリダイレクトするメソッドを全部準備することによって必要とされる機能を実装することになります。

このような労力に比べるとMopsにおける多重継承が目的の機能を果たすクラスをいかにシンプルに記述することができるか理解していただけると思います。


戻る