Prototype based OOP と Class based OOP
- ref:Kazuho@Cybozu Labs: JavaScript は、なぜプロトタイプベースなのか
- ref:404 Blog Not Found:javascript vs perl - オブジェクトのメモリー効率
- ref:Kazuho@Cybozu Labs: re: javascript vs perl - オブジェクトのメモリー効率
- ref:404 Blog Not Found:メモリー効率は所詮実装次第
最後のkazuhoさんのコメントが
挙げられている例のようにテクニックを使えば、さまざまなことができます。C 言語でだって、オブジェクト指向のコードを書くことができます。
ではなぜ C++ が、オブジェクト指向の開発で使われるのでしょう? C よりも C++ のほうが OO するのに向いているからですよね。同様の理由で、Prototype-based OO のほうが Class-based OO よりもメモリに優しいモデルである、と言えると私は考えています。
なわけだけど、Ruby や Python みたいな実行時にインスタンスやクラスの挙動を書き換えられる言語と比較したら Prototype based と Class based の本質的な違いって Syntax 以外にとくにないんじゃないかと思う。いやまぁ、Ruby なんかだとメソッドとは別にインスタンス変数を保持しなけりゃいけないからそりゃ多少メモリを食うだろうが、結局、メソッドとインスタンス変数のシンボルテーブルの切り方以上の問題ではなく、メソッドのディスパッチを言語レベルでサポートしてないC言語とは比べるべくも無いような。
そもそも、ランタイムにオブジェクトやスコープごとにシンボルテーブルを作るような言語処理系でメモリ効率言われてもなぁ、という気がしないでもない。
ところで、Ruby で method_missing を使って prototype っぽい挙動をさせようとすると以下のような感じでいいんだろうか。メソッドの場合は特異メソッド等で対処。メソッドのコピーとかできないけど。まぁ、ostruct.rb からパクって簡略化しただけだけどな。
class PrototypeBase def initialize(hash=nil) @table = {} if hash for k,v in hash @table[k.to_sym] = v end end end def prototype self.class::PROTOTYPE end def method_missing(mid, *args) mname = mid.id2name len = args.length if mname =~ /=$/ if len != 1 raise ArgumentError, "wrong number of arguments (#{len} for 1)", caller(1) end mname.chop! @table[mname.intern] = args[0] elsif len == 0 if @table.has_key? mid @table[mid] else prototype[mid] end else raise NoMethodError, "undefined method `#{mname}' for #{self}", caller(1) end end end class A < PrototypeBase PROTOTYPE = { :y => 20 } end if $0 == __FILE__ o = A.new o.x = 10 puts o.x puts o.y o.y = 5 puts o.y puts A.new.y end