Ruby 類的本質
前面的章節中介紹了類的定義與實例化,本章節我們來深入探討一下類的本質。
1. 超類
現在我們定義一兩個類:Student和Person,令Student繼承Person,然后通過調用superclass方法來輸出它的超類。
實例:
class Person
end
class Student < Person
end
puts Student.superclass
# ---- 輸出結果 ----
Person
由上面輸出可知,超類實際上是當前類所繼承的類。
現在讓我們繼續獲取Person的超類。
實例:
puts Person.superclass
# ---- 輸出結果 ----
Object
Object是一個特殊的類,所有的類都是Object的子類。(在Ruby 1.8 ~ 1.9中,每個類都是BasicObject的子類)
我們輸出Object的超類,得到了BasicObject,它是Ruby類結構體系的根節點。
實例:
puts Object.superclass
# ---- 輸出結果 ----
BasicObject
2. 類實際上是對象
現在讓我們實例化Person,獲得一個person對象。還記得class方法嗎,它是獲取一個對象所屬的類的方法。
實例:
person = Person.new
puts person.class
puts Person.class
# ---- 輸出結果 ----
Person
Class
解釋:第一條輸出結果代表了person對象所屬于Person類,同理,第二條輸出結果代表了Person類,是Class類的對象。
Tips:每一個類都是Class的實例,這也意味著Class類也是Class類自己的實例。
實例:
puts Class.class
# ---- 輸出結果 ----
Class
因此綜上所述,所有的類都是對象。
Tips:Class的超類是Module,所以可以說所有的類其實也是模塊。
實例:
puts Class.superclass
puts Module.superclass
# ---- 輸出結果 ----
Module
Object
3. 祖先鏈
由之前的學習,我們知道了Ruby的方法都是定義在類中,調用方法前,Ruby會在對象的類中查找到那個方法,現在讓我們學習一下它的運作原理。
舉一個例子:
"hello".reverse
在這里,"hello"調用了reverse方法,"hello"這個字符串對象作為調用方法的對象被稱為接收者(receiver)。
現在我們在Person中定義方法。
實例:
class Person
def age
18
end
def name
"Andrew"
end
end
class Student < Person
end
student = Student.new
puts student.name
puts student.age
# ---- 輸出結果 ----
Andrew
18
解釋:剛剛這個例子表示了一個簡單的繼承關系。Ruby在查找方法時遵循一個先右一步再向上的原則,如剛剛的student對象,Ruby會先找到他的類Student(class方法),從這個類中沒有找到方法,然后繼續向上找它的超類(superclass方法),從Person中找到了age和name。
這種方法查找順序的機制,我們可以使用祖先鏈(ancestors)來表示。
實例:
p Student.ancestors
# ---- 輸出結果 ----
[Student, Person, Object, Kernel, BasicObject]
解釋:我們可以看到,祖先鏈是從student的類逐級向上查找的,需要注意的是,Kernel是一個模塊,因為Object類include了Kernel模塊,所以Kernel也會出現在祖先鏈里面。
在之前的學習中我們了解到,在方法名稱相同的時候,include模塊不會覆蓋類原本的方法,而Ruby 2.0以后的perpend方法會覆蓋掉類原本的方法。因此使用include或prepend引入模塊會出現兩種不同的祖先鏈。
實例:
module A
end
module B
end
class Person
prepend A
include B
end
class Student < Person
end
p Student.ancestors
# ---- 輸出結果 ----
[Student, A, Person, B, Object, Kernel, BasicObject]
解釋:從比較容易理解的層面上,因為模塊A的優先級比Person更高,模塊B的優先級比Person低,所以當查到Student之后,先會去找模塊A,然后是Person,然后是模塊B …
4. 小結
本章節中的重點是:
- 所有的類都是
Object的子類。(Ruby 1.8 - 1.9 是BasicObject); - 所有的類都是
Class的實例,包括它本身; - 所有對象的方法都在類中,根據祖先鏈來進行查找;
- 模塊會根據
include和perpend出現在祖先鏈中不同的位置上。
杜驍 ·
2025 imooc.com All Rights Reserved |