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