トレイトについてのモヤモヤのメモ

Traits: Composable Units of Behaviour のイントロ部分を訳してみました の続きです。


* * *


Traits は、平たく言えば 「has-a は委譲せよ!」の代替・・というか「えー?運用でカバーってカッコ悪くない?」みたいな物なのかな?と思います。そう考えると、C# の プロパティに発想のベクトルがちょっとだけ似てる?

ただTraitは、Strategy パターン的な実装再利用構造の構築の単純な代替ではありません。Traitは、

  • 再利用によりクラス内が変にコンポジット化しない
  • useするクラスのインターフェイス(=型)を拡張してしまう

特徴があります。そこが委譲に対する売りだとおもうのだけれど、特に後者について、トレイトの立ち位置は徹底して「再利用」だから知らんぷり(?)なのが、イマイチ釈然と来ないところです。

この論文の2章には、

Note that this section is focused on reusability issues. Other problems with inheritance such as implementation difficulties [14, 43] and conflicts between inheritance and subtyping [2, 25, 26] are outside the scope of this paper.


ノート。このセクションは再利用性に焦点を当ててますにゃ。継承の他の問題(たとえば実装の難しさ)とか、継承とサブタイピングの間の競合(アッチを立てればコッチが立たず、あーうー..)とかは、この論文では見なかったことにします。

みたいにいわれても、ちょっとまってよ! トレイトのuse は、型を拡張しちゃうのだから「見なかったことにしてね(てへっ」・・は無いでしょう、とか思ってしまいました。

実際、Java の Interface のようなものと Traits はとても相性が悪いと思います。(どうすれば両立する?? Traits も Interface を持つ?でもそれって 継承木から独立できなくなりそう)今のところ、(静的/動的)ダッグタイピングありきなのかな?と思います。


* * *


もう一つよくわかってないのは、トレイトの状態を持たないあたりのコダワリです。説明では「状態持つと多重継承やミックスインみたいに大変になっちゃうじゃん」とか書いてあるけど、それって単に その多重継承やミックスインがダメな実装であるだけでは? と、思います。すくなくとも Ruby の Mix-in とかでは 「大変になっちゃった」と感じません。

うーん、でもカプセル化が破壊されると考えるべきなのかな? Mix-in 同士をフィットさせる際にメンバ変数とその名前を意識しなくてはいけないのはイクナイとか。うにゅー。「実装だけでなく概念的に宜しくない」あたりがよくわかりません。

トレイトはクラス生成に対するメタな部品で、あくまでメソッドセットに過ぎない・・という当たりもキモいです。

GNU Smalltalk のTraits実装とかでは、トレイトとクラスってシンボルでつながってるのじゃなくって、クラス生成時のトレイトのメソッドセットのスナップショットを Fix して取り込んちゃうんですよね。そのあたりが、Smalltalk 的にはたまらなくキモく感じます。became とかでつじつまあわせるのかな?

オブジェクトの責務分散協調系で描く世界に対して、トレイトはちょっと異質でメタな感じがします。それは(他のOOPLではイザ知らず) Smalltalk としては、クラスですらオブジェクトなシンプルな ルールを崩してしまうように思えます。(Class にメッセージは送れても、Trait にメッセージは送れない)すみません。そんなこたぁないです。


* * *


とはいいつつ、Traits といわれるとしっくりこないけど Perlのように Roles と言われるとしっくり来るような気もしていて、結局 Traits は だいたいCRCカードの「責務」の単位 くらいになるのかな(というかそれを表現する抽象化部品になるのかな)と思うのだけれど、でも Interface じゃなくあくまでの実装の再利用なのですよね。

たとえば、Sather のクラスライブラリは、細いInterface をガンガン継承していって、階層の最後の最後で始めて実装を行うスタイルなのだけれど、そこで トレイトを useしていって構築する・・ってイメージでいいのかな?とかとか。


* * *


うーん、もやもや。