ruby object model (2)
這幾天想這個 object model 感覺快要腦炸了。奇怪,應該沒那麼難啊,
為什麼一直搞得很困惑??是我變笨了還是其實真的很複雜?
Rubinius 試半天,認為圖應該沒畫錯,事實上應該確實是 Rubinius 的
object model 沒錯。但事實上,在 MRI 和 JRuby 又不一樣...
可以看這兩個 rubinius tickets:
1. calling a 'class' method on an object's metaclass should
invoke the class method of the object's class
2. Kernel and IncludedModule
第一個的重點是:
http://gist.github.com/31903
b = B.new
# false in Rubinius, true in MRI, JRuby
p b.metaclass.superclass.object_id == B.metaclass.object_id
b.meta_def(:cheese) {'cheshire'}
# false in all implementation
p b.metaclass.superclass.object_id == B.metaclass.object_id
1. MetaClass d 的 superclass 不是 D, 而是 MetaClass D !!
2. MRI/JRuby 的 metaclass 會改變!
第一點會造成推斷出來的 method lookup 規則有例外!
第二點則是... Charles L 認為這是合理的。
不過我還不太懂他的意思,我只知道使用前和使用後有所差異是詭異的。
就算這應該是 lazily created, 這是當然的,畢竟我們不可成真的產生
窮盡記憶體的 metaclasses. 但是也不能因此先丟個毫無關係的 B 進去吧?
copy on write 仍然必須維持 proxy 的特性啊。我不覺得應該因此改變結構。
第二個重點則是:
http://gist.github.com/30606 的第三則
MRI 和 JRuby 大概是不管怎麼樣,反正插進去就是了。所以他不會影響到已存的
class 們。但是 Rubinius 卻會翻之前的 module 出來重新一個個插進去:
kernel/delta/module.rb: 63~74
if ancestors.include? mod
ancestor = superclass_chain.find do |m|
m.module == mod if m.kind_of?(IncludedModule)
end
ancestor.module.included_modules.each do |included_mod|
included_mod.send :append_features, ancestor
included_mod.send :included, ancestor
end
else
mod.send :append_features, self
mod.send :included, self
end
這個.... 我不知道誰的作法比較好,總之不一樣就是了。
其他一點相關的知識:
=== 是判斷 kind_of? 和 ==(或 eql? equal? 搞不清楚)
但奇怪的是 Fixnum === Fixnum 又是 false.
而 Fixnum === 1 和 1 === 1 又是 true.
思考方法是,你覺得 case 裡面應該要怎麼樣判斷正確?
所以至少就會是 equality, kind_of, 還有 includsion.
例如 (1..10) === 5 也要是 true.
個人建議是不要用這個 method, 那是留給 case 用的。
然後 kind_of? 的判斷並不是看 ancestors,
而是 ancestors 和 metaclass 的 ancestors 都算。
因此 Fixnum.kind_of? Object.metaclass 也會是 true.
這些都算是為了方便所以做的,所以規則有點恐怖...
==
唉,不過我真有點不想再想這個了,覺得快腦炸了。
0 retries:
Post a Comment
Note: Only a member of this blog may post a comment.