言語ゲーム

とあるエンジニアが嘘ばかり書く日記

Twitter: @propella

ぼくも Traits について考える。

なんだか Traits について考えるのが流行っているみたいなので僕も考えてみた。Traits というのは何かというと、端的には多重継承とコードの重複を同時に避ける仕組みだ。

例えば、長方形、正三角形、正方形があるとき、正方形は長方形の仲間だろうか、正三角形の仲間だろうか。

  • 長方形の仲間だという事にすると、長方形と正方形に共通する、面積の求め方や作図の仕方をまとめる事が出来る。
  • 正三角形と正方形をまとめると、全ての辺が同じ長さという事をまとめる事が出来る。

多重継承を使えば、正方形を両方の仲間だとみなす事も出来るがこれを避けたい沢山の理由がある(が、忘れたので書かない)。問題は物の性質を現すのに継承というのがあまりにも大雑把だという事で、Traits は、多重継承を避ける為に使う Ruby の Module のような物だ(というかメソッド名重複の解決以外は Module と一緒では?)。これは物の状態と性質を分けて、状態は多重継承出来ないが、性質は多重継承しても良いという考え方だ。

  • 正三角形と正方形は、正多角形特有の、一辺の長さの状態を持つ。
  • 正方形は、長方形と共通の、角度が直角という性質を持つ。

状態と性質の違いは次の通り、状態とは、ある物の性質を現すのに最低限必要な変数だ。例えば長方形には縦と横の長さを表す変数二つ。正方形と正三角形については一辺の長さだけが分かればよいので変数は一つ。他の長さは一辺から全て求まる。性質は、例えば辺と辺の角度が直角であったり、隣り合う二辺を掛ければ面積になるという物だ。Traits では、状態に Class の継承を使い、性質に Traits を使う。あるクラスは必ず一つスーパークラスを持つが、Traits は沢山持っても良い。

なぜこう言う事を考えているかというと、Alex が Traits に状態を持たせるという事を言っていて、なんか邪道な匂いがするんだけど、なぜそう匂うのかうまく説明出来ないから。

僕は Traits が状態を持たないという事がとても大切だと思っている。状態を持たない操作をプログラマは、関数的といって神聖な物とみなす。なぜなら、状態を持たない操作、関数は、実行前に最適化出来るから。例えば、プログラム内に、面積の値を使う大量の操作があったとする。素直な実装は、面積の値が必要なたびに縦×横を計算する事だが、まあ勿体無いので一時変数に入れるだろう。面積を求める操作が状態を変えない(副作用が無い) 事があらかじめ分かっていれば、コンパイラは一時変数に入れる操作(メモ化)を勝手にやってくれる。メモ化はコンピュータがやるべきで、人間がやるべきでは無いという主張。

Traits を、副作用を起こさない操作の集合だとみなす事は出来ないだろうか、副作用は必ず Class の側だけで起こる。天井を見上げてちょっと考えるだけで色々穴が思い浮かぶのだが、とりあえずのスタート地点。プログラムが「行為」でなく、「意図」を表す物であるべきだという観点に立てば、この性質は必須だろう。特に、あなたが一時変数の山である Squeak のレイアウト関連のスパゲッティコードを見たことがあれば、是非我が家にも一つ欲しいと思うに違いない。