亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

Ruby 類的本質

前面的章節中介紹了類的定義與實例化,本章節我們來深入探討一下類的本質。

1. 超類

現在我們定義一兩個類:StudentPerson,令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會先找到他的類Studentclass方法),從這個類中沒有找到方法,然后繼續向上找它的超類(superclass方法),從Person中找到了agename

這種方法查找順序的機制,我們可以使用祖先鏈ancestors)來表示。

實例:

p Student.ancestors

# ---- 輸出結果 ----
[Student, Person, Object, Kernel, BasicObject]

解釋:我們可以看到,祖先鏈是從student的類逐級向上查找的,需要注意的是,Kernel是一個模塊,因為Object類include了Kernel模塊,所以Kernel也會出現在祖先鏈里面。

在之前的學習中我們了解到,在方法名稱相同的時候,include模塊不會覆蓋類原本的方法,而Ruby 2.0以后的perpend方法會覆蓋掉類原本的方法。因此使用includeprepend引入模塊會出現兩種不同的祖先鏈。

實例:

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. 小結

本章節中的重點是:

  1. 所有的類都是Object的子類。(Ruby 1.8 - 1.9 是BasicObject);
  2. 所有的類都是Class的實例,包括它本身;
  3. 所有對象的方法都在類中,根據祖先鏈來進行查找;
  4. 模塊會根據includeperpend出現在祖先鏈中不同的位置上。