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

Ruby 的 Singleton 類

Ruby 對象模型有一個很特殊的存在,他就是單例類Singleton Class),本章節(jié)中我們會對單例類做一個簡單的介紹。

1. 什么是單例類

讓我們從一個簡單的例子開始:

實例

class Person
  def a_name
    'Andrew'
  end
end

person = Person.new
puts person.a_name
puts person.class.instance_methods.grep /name/

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

這個是一個簡單的例子,在類的本質(zhì)中我們學(xué)習(xí)到了,如果要查找一個對象中的方法,要從他的類中查找,因為方法都是定義在類中的。

類其實也是對象,那么當(dāng)我們定義類方法的時候,同理,方法應(yīng)該存在于Class類中的,但是答案卻是否定的。

實例:

class Person
  def self.list
    [ 'Andrew', 'Tom', 'Alice' ]
  end
 
end

p Person.list
p Person.class.instance_methods.grep /list/

# ---- 輸出結(jié)果 ----
["Andrew", "Tom", "Alice"]
[]

那么這個類方法到底放在了哪里呢,答案就是存在于單例類中。

我們可以使用singleton_class來獲取一個對象的單例類。

實例:

class Person
  def self.list
    [ 'Andrew', 'Tom', 'Alice' ]
  end
 
end

p Person.list
p Person.singleton_class.instance_methods.grep /list/

# ---- 輸出結(jié)果 ----
["Andrew", "Tom", "Alice"]
[:list]

**解釋:**當(dāng)我們定義self.list的時候,實際上是告訴Ruby打開self的單例類,并在其定義list方法。

同理可知,所有的對象他們的方法實際上都存在于單例類之中。

實例:

class Person
  def a_name
    'Andrew'
  end
end

person = Person.new
puts person.a_name
puts person.singleton_class.instance_methods.grep /name/

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

2. 單例類與類、對象之間的關(guān)系

現(xiàn)在讓我們定義一個Student類和Person類。

實例:

class Person
  def a_name
    'Andrew'
  end 
end

class Student < Person
end

student = Student.new
p student.a_name

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

讓我們輸出它的祖先鏈:

p Student.ancestor

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

讓我們從頭輸出一下它祖先鏈類的部分:

p student.class
p student.class.superclass
p student.class.superclass.superclass
p student.class.superclass.superclass.superclass

# ---- 輸出結(jié)果 ----
Student
Person
Object
BasicObject

現(xiàn)在讓我們在中間輸出它的每一個對象的單例類:

p student.singleton_class
p student.class
p student.class.singleton_class
p student.class.superclass
p student.class.superclass.singleton_class
p student.class.superclass.superclass
p student.class.superclass.superclass.singleton_class
p student.class.superclass.superclass.superclass
p student.class.superclass.superclass.superclass.singleton_class

# ---- 輸出結(jié)果 ----
#<Class:#<Student:0x007f82f4170060>>
Student
#<Class:Student>
Person
#<Class:Person>
Object
#<Class:Object>
BasicObject
#<Class:BasicObject>

Tips:單例類輸出前面會有一個#,比如:通常我們說Person的單例類是#Person。

實例對象的單例類的超類是實例對象的類。

p student.class
p student.singleton_class.superclass

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

類的單例類的超類等于類的超類的單例類。

p student.class.singleton_class.superclass
p student.class.singleton_class.superclass.superclass
p student.class.singleton_class.superclass.superclass.superclass

p student.class.superclass.singleton_class
p student.class.superclass.superclass.singleton_class
p student.class.superclass.superclass.superclass.singleton_class

# ---- 輸出結(jié)果 ----
#<Class:Person>
#<Class:Object>
#<Class:BasicObject>
#<Class:Person>
#<Class:Object>
#<Class:BasicObject>

單例類同樣也是Class類的對象。

p student.singleton_class.class
p student.class.singleton_class.class

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

3. 打開單例類

我們可以通過class <<來打開單例類并且在其中定義方法。

實例:

普通實例對象:

class Person
end

person = Person.new

class << person
  def name
    'Andrew'
  end
end

puts person.name

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

對于類您同樣可以這么使用:

class Person
end

class << Person
  def list
    ['Andrew', 'Alice']
  end
end

p Person.list

# ---- 輸出結(jié)果 ----
["Andrew", "Alice"]

或者在類的內(nèi)部打開單例類:

class Person
  class << self
    def list
      ['Andrew', 'Alice']
    end
  end
end

p Person.list

# ---- 輸出結(jié)果 ----
["Andrew", "Alice"]

4. 小結(jié)

本章節(jié)我們學(xué)習(xí)了 Ruby 中單例類的知識,學(xué)習(xí)到了:

  1. 定義對象的方法的時候(包括類),所有的方法都是定義到了單例類中。
  2. 每一個對象都有單例類(包括類)。
  3. 實例對象的單例類的超類是實例對象的類。
  4. 類的單例類的超類等于類的超類的單例類。
  5. 單例類同樣也是Class類的對象。
  6. 我們可以通過class <<來打開單例類并定義方法。