限界

図形編集アプリケーションを作っていて,

class IShape
  ...
end

class Polygon < IShape
  ...
end

class Line < IShape
  ...
end

class ShapeList
  ...
end

みたいな,図形を表現するクラス群があったとする.Lineは始点と終点の座標を保持する.Polygonは各頂点の座標を保持する.現在アクティブな図形の全ての図形は,ShapeListのインスタンスに保持される.

さて,このとき,編集はどうするべきだろうか.

Lineに対しては始点と終点の編集ができないといけないし,Polygonに対しては各頂点の編集ができないといけない.じゃあ,Shapeに,hdとtlというLine用のプロパティと,vertexesなんていうPolygon用のプロパティを両方実装しましょうなんていうのは,ナンセンスの極みである.じゃあどうすればいいのか.これはオブジェクト指向プログラミングという文脈では,奇麗に実装することはできないパターンの一つだ.Visitorパターンなんかが解決策になりそうな気がしたこともあったが,そんなややこしいパターンを持ち出さなくてはならないような問題でもない.Shapeにtypeなんていうプロパティを作って,実行時にLineかPolygonかを判定して,編集メソッドを切り換えるようにすればいいだけなのだ.*1 *2

そんなプログラムをTyping Rubyで検証するとどうなるのか?多分ちゃんと検証できない.「ShapeListに入っているオブジェクトはIShapeであるべきで,その他のメソッドを呼び出すのは厳禁である」という判断では,意味もなくエラーが出てしまうことになる.こういう頻発する,効果的な他の対応策が存在しないパターンで,エラーの誤認が発生するのは問題である.

現在のRubyではこういう状況はお手上げで,Typing Rubyには手も足も出ない.ダルマさん状態だ.C++C#を考えれば,対応策は明らかである.明示的なキャスト(dynamic_cast)を導入すれば良い.Rubyで言えば,Object Adaptationとでも名付けられることになるだろうか.なんだ,Object Adaptation便利じゃないか!

*1:Windowsプロフェッショナルゲームプログラミングにもそう書いてあった

*2:OCamlだったら,パターンマッチが使えて幸せになれるかな?