Ruby 以外に module 機能のようなものがある言語ってあったっけ? 2


id:sumim:20061106:p1 の続き…というより、オマケ?


Ruby や Strongtalk のものとはセマンティックスを異にしますが、Squeak システムにおいて 3.9(起動するには別途 Squeak VM と SqueakV3.sources が必要)より採用されることになったミックスイン機構である Traits ではどうなっているかも調べてみました。

式と評価結果(文字を入力できる場所で式をタイプして入力し(念のため選択して)、print it(alt/cmd + p)で結果が得られます)
C2 new init   " => ' T[C2] T[C1] Object ProtoObject' "

Traits の場合、トレイト(モジュール)を use(include)しても、元のクラスの super の挙動は変わらないので、C1 、C2 には #init は定義していないのと、同時に、T(M に相当)の #init にちょっと細工をしてどのようなコンテキストで起動されているのかが区別可能なようにしてみました。


なお念のため、Smalltalk において super は、Ruby の super のようにスーパークラスのメソッドのエイリアスではなく、self と同様、レシーバに関連づけされた擬変数にすぎないので注意してください。self との違いは、メソッド探索の際、レシーバが属するクラスに定義されたメソッドを無視する特殊な機構が働くこと(この結果、必然的にスーパークラスに定義されたメソッドがコールされることになる…というカラクリ)です。

定義(ファイルイン用……C2.st などとして保存したものを、File List → filein ボタン、あるいは、適当な場所にコピペして選択後、シフト黄ボタンメニューより file it in(alt/cmd + shift + g)などとして読み込ませます)
Trait named: #T
   uses: {}
   category: 'Category-Name'!

!T methodsFor: 'as yet unclassified'!
init
   ^ ' T[', thisContext methodClass name, ']', super init! !


!ProtoObject methodsFor: 'as yet unclassified'!
init
   ^ ' ProtoObject'! !


!Object methodsFor: 'as yet unclassified'!
init
   ^ ' Object', super init! !


Object subclass: #C1
   uses: T
   instanceVariableNames: ''
   classVariableNames: ''
   poolDictionaries: ''
   category: 'Category-Name'!

C1 subclass: #C2
   uses: T
   instanceVariableNames: ''
   classVariableNames: ''
   poolDictionaries: ''
   category: 'Category-Name'!


トレイト同士のコンフリクトには神経質(…というか、それがウリ)な Traits という印象だったので、重複呼び出しはしないかな…と予想していたのですが、そんな私には意外な結果になりました。もっとも、何か文句を言ってくるなら C2 定義の時点なので、このときすでにスルーされているということは、もしかしたらこのような継承ツリーパス内での重複指定は想定外なのかもしれません(あくまでトーシローの想像ですのであしからず)。