第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

Ruby 類的本質(zhì)

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

1. 超類

現(xiàn)在我們定義一兩個類:StudentPerson,令Student繼承Person,然后通過調(diào)用superclass方法來輸出它的超類。

實例:

class Person
end

class Student < Person
end

puts Student.superclass

# ---- 輸出結(jié)果 ----
Person

由上面輸出可知,超類實際上是當(dāng)前類所繼承的類。

現(xiàn)在讓我們繼續(xù)獲取Person的超類。

實例:

puts Person.superclass

# ---- 輸出結(jié)果 ----
Object

Object是一個特殊的類,所有的類都是Object的子類。(在Ruby 1.8 ~ 1.9中,每個類都是BasicObject的子類)

我們輸出Object的超類,得到了BasicObject,它是Ruby類結(jié)構(gòu)體系的根節(jié)點。

實例:

puts Object.superclass

# ---- 輸出結(jié)果 ----
BasicObject

2. 類實際上是對象

現(xiàn)在讓我們實例化Person,獲得一個person對象。還記得class方法嗎,它是獲取一個對象所屬的類的方法。

實例:

person = Person.new
puts person.class
puts Person.class

# ---- 輸出結(jié)果 ----
Person
Class

解釋:第一條輸出結(jié)果代表了person對象所屬于Person類,同理,第二條輸出結(jié)果代表了Person類,是Class類的對象。

Tips:每一個類都是Class的實例,這也意味著Class類也是Class類自己的實例。

實例:

puts Class.class

# ---- 輸出結(jié)果 ----
Class

因此綜上所述,所有的類都是對象。

Tips:Class的超類是Module,所以可以說所有的類其實也是模塊。

實例:

puts Class.superclass
puts Module.superclass

# ---- 輸出結(jié)果 ----
Module
Object

3. 祖先鏈

由之前的學(xué)習(xí),我們知道了Ruby的方法都是定義在類中,調(diào)用方法前,Ruby會在對象的類中查找到那個方法,現(xiàn)在讓我們學(xué)習(xí)一下它的運作原理。

舉一個例子:

"hello".reverse	

在這里,"hello"調(diào)用了reverse方法,"hello"這個字符串對象作為調(diào)用方法的對象被稱為接收者receiver)。

現(xiàn)在我們在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

# ---- 輸出結(jié)果 ----
Andrew
18

解釋:剛剛這個例子表示了一個簡單的繼承關(guān)系。Ruby在查找方法時遵循一個先右一步再向上的原則,如剛剛的student對象,Ruby會先找到他的類Studentclass方法),從這個類中沒有找到方法,然后繼續(xù)向上找它的超類(superclass方法),從Person中找到了agename

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

實例:

p Student.ancestors

# ---- 輸出結(jié)果 ----
[Student, Person, Object, Kernel, BasicObject]

解釋:我們可以看到,祖先鏈?zhǔn)菑膕tudent的類逐級向上查找的,需要注意的是,Kernel是一個模塊,因為Object類include了Kernel模塊,所以Kernel也會出現(xiàn)在祖先鏈里面。

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

實例:

module A
end

module B
end

class Person
  prepend A
  include B
end

class Student < Person
end

p Student.ancestors

# ---- 輸出結(jié)果 ----
[Student, A, Person, B, Object, Kernel, BasicObject]

解釋:從比較容易理解的層面上,因為模塊A的優(yōu)先級比Person更高,模塊B的優(yōu)先級比Person低,所以當(dāng)查到Student之后,先會去找模塊A,然后是Person,然后是模塊B …

4. 小結(jié)

本章節(jié)中的重點是:

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