首先要知道,Ruby中的類(lèi)也是對象,類(lèi)相比于其他對象特殊的地方在于能夠產(chǎn)生對象,既然類(lèi)是對象,那么它顯然也有類(lèi),也就是所謂類(lèi)的類(lèi),這個(gè)類(lèi)的類(lèi)在Ruby中就是類(lèi)的metaclass,圖中的(OtherClass),(OtherClass)就是類(lèi)OtherClass的klass(C層次),(OtherClass)存儲了類(lèi)的方法(類(lèi)方法)和類(lèi)的實(shí)例變量,并且是唯一的且不可實(shí)例化。在Ruby層次上我們想操作(otherclass)應該類(lèi)似:
class OtherClass
end
class<<OtherClass
attr_accessor:name #name是OtherClass的實(shí)例變量
def test
p 'hello'
end
end
OtherClass.name='1'
p OtherClass.name
OtherClass.test
圖中的instance是OtherClass的一個(gè)實(shí)例,那么顯然instance的class是OtherClass,可是圖中的(instance)又是什么呢?(instance)就是對象的singleton類(lèi),singleton類(lèi)這個(gè)名稱(chēng)怪怪的,不過(guò)每個(gè)對象只能有一個(gè)singleton類(lèi)的角度上說(shuō)也可以理解??纯聪旅娴睦樱?br>end
class<<OtherClass
attr_accessor:name #name是OtherClass的實(shí)例變量
def test
p 'hello'
end
end
OtherClass.name='1'
p OtherClass.name
OtherClass.test
class OtherClass
end
instance=OtherClass.new
class<<instance
def test
p "a.test"
end
attr_accessor:name
end
instance.test
instance.name="dennis"
p instance.name
end
instance=OtherClass.new
class<<instance
def test
p "a.test"
end
attr_accessor:name
end
instance.test
instance.name="dennis"
p instance.name
instance通過(guò)OtherClass.new創(chuàng )建,但是此時(shí)(instance)還不存在,這與(OtherClass)情況不同,每個(gè)類(lèi)一經(jīng)創(chuàng )建就有一個(gè)metaclass,而對象就不一樣,只有當你通過(guò)class<<instance語(yǔ)法創(chuàng )建的時(shí)候,(instance)才被創(chuàng )建。注意test方法和name變量都將是instance對象特有的,類(lèi)OtherClass并沒(méi)有改變。觀(guān)察下,發(fā)現(instance)繼承于OtherClass,引出類(lèi)的metaclass與對象的singleton類(lèi)的又一個(gè)區別:類(lèi)的metaclass繼承自父類(lèi)的metaclass,而對象的singleton類(lèi)則是繼承于對象的class。
那么當我們調用instance.class的時(shí)候,怎么不返回(instance)?這是cruby在底層做了處理,instance的class在cruby層次是(instance),當查找的時(shí)候忽略了singleton類(lèi)以及下面將要談到的include模塊的代理類(lèi),沿著(zhù)繼承鏈上查找:
86 VALUE
87 rb_obj_class(obj)
88 VALUE obj;
89 {
90 return rb_class_real(CLASS_OF(obj));
91 }
76 VALUE
77 rb_class_real(cl)
78 VALUE cl;
79 {
80 while (FL_TEST(cl, FL_SINGLETON) || TYPE(cl) == T_ICLASS) {
81 cl = RCLASS(cl)->super;
82 }
83 return cl;
84 }
(object.c)
核心代碼就是:
while (FL_TEST(cl, FL_SINGLETON) || TYPE(cl) == T_ICLASS) {
cl = RCLASS(cl)->super;
}
其中FL_TEST(cl,FL_SINGLETON)用于測試是否是singleton類(lèi),而TYPE(cl)==TL_ICLASS是否是包含模塊的代理類(lèi),TL_ICLASS的I就是include的意思。
圖中類(lèi)OtherClass繼承Object,這個(gè)是顯而易見(jiàn)的,不再多說(shuō)。而Object、Class和Module這三個(gè)類(lèi)是沒(méi)辦法通過(guò)API創(chuàng )建的,稱(chēng)為元類(lèi),他們的之間的關(guān)系如圖所示,Object的class是Class,Module繼承Object,而Class又繼承Module,因此Class.kind_of? Object返回true,這個(gè)問(wèn)題類(lèi)似先有雞,還是先有蛋的問(wèn)題,是先有Object?還是先有Class?而cruby的解決辦法是不管誰(shuí)先有,創(chuàng )建Object開(kāi)始,接著(zhù)創(chuàng )建Module和Class,然后分別創(chuàng )建它們的metaclass,從此整個(gè)Ruby的對象模型開(kāi)始運轉。
1243 rb_cObject = boot_defclass("Object", 0);
1244 rb_cModule = boot_defclass("Module", rb_cObject);
1245 rb_cClass = boot_defclass("Class", rb_cModule);
1246
1247 metaclass = rb_make_metaclass(rb_cObject, rb_cClass);
1248 metaclass = rb_make_metaclass(rb_cModule, metaclass);
1249 metaclass = rb_make_metaclass(rb_cClass, metaclass);
(object.c)
那么當我們調用Class.class發(fā)生了什么?Class的klass其實(shí)指向的是(Class),可根據上面的代碼,我們知道會(huì )忽略這個(gè)(Class),繼續往上找就是(Module),同理找到(Object),而(Object)繼承自Class,顯然Class的類(lèi)仍然是Class,Class的類(lèi)的類(lèi)也是Class,多么有趣。同理,Object.class和Module.class都將是Class類(lèi)。
再來(lái)看看include模塊時(shí)發(fā)生的故事。include模塊的過(guò)程如下圖所示:

include模塊,本質(zhì)上是在對象或者類(lèi)的klass和super之間插入了一個(gè)代理類(lèi)iclass,這個(gè)代理類(lèi)的方法表(m_table)和變量表(iv_table)分別指向了被包含的模塊的方法表和變量表(通過(guò)指針,因此當包含的Module變化的時(shí)候,對象或者類(lèi)也能相應變化),那么在查找類(lèi)或者對象的class的時(shí)候,上面已經(jīng)說(shuō)明將忽略這些代理類(lèi)。
posted on 2007-09-29 09:43 dennis 閱讀(274) 評論(0) 編輯 收藏 所屬分類(lèi): 動(dòng)態(tài)語(yǔ)言 & rails 、my open-source 、源碼解讀

