delegateでプロトタイプベース継承
delegateを使うと、任意のオブジェクトに処理を移譲するクラスを作ることができます。これを利用してJavaScriptなプロトタイプベースっぽい継承ができます。
require 'delegate' #superクラス class Animal def walk () puts "teku teku." end end #subクラス #SimpleDelegatorを継承しプロトタイプに処理を移譲する。 class Kitten < SimpleDelegator def initialize() super(PROTOTYPE) end # Kittenのプロトタイプ PROTOTYPE = Animal.new end # 実行 Kitten.new.walk
実行結果です。walkはKittenでは定義されていないので、PROTOTYPEであるAnimalのwalkが呼ばれます。
teku teku.
こんなメソッドを定義してもいい。
# objにprototypeを継承させる。 def extends( obj, prototype ) obj.instance_variable_set("@__proto__", prototype) def obj.method_missing(message, *arg) @__proto__.send(message, *arg) end return obj end # サンプル extends( Object.new, Animal.new ).walk
実行結果です。
teku teku.
何がうれしいか
- 動的な継承ができる
- インスタンスを継承できる
とかメリットはあるかなとは思います。でもカオスだ。特異メソッドとか動的継承を多用したコードをJavaプログラマに見せたら泣きそうになるに違いない。あと性能も気になるところ。method_missingとか重くないのかな。
2007-12-25 追記
今気がついたけど、これだと継承元インタンスのAPI内での「self」が継承元インタンスになりますね。orz.そうかそういう問題があるのか。