2016-11-02 113 views
4

下面的代碼輸出「我是物」。爲什麼「class << self」中的自我是指類?

class Thing 
    class << self 
     def foo 
     puts "I am #{self}." 
     end 
    end 
end 

Thing.foo 

我認爲「自我」是指Thing類型的對象,但它指的是Thing類。我從之前的一個問題中收集到的(鏈接在評論中),這與Thing是Object的一個實例有關。在「自我」是指Thing作爲一個實例的情況下,以< < <自身實際執行的塊是否以「Thing」這裏發生了什麼?

+2

相關問題:http://stackoverflow.com/questions/6182628/ruby-class-inheritance-what-is-double-less-than – nickackerman42

回答

5

內部方法self指的是在類/模塊定義內部,但在任何方法之外的實例 - 類/模塊本身。

class Thing 
    puts self.inspect 
    def foo 
    puts self.inspect 
    end 
end 
puts "===" 
Thing.new.foo 

嘗試上面的代碼,你可能會看到發生的事情有:類是首先被解析,並且正在執行第一puts。然後puts "==="打印出"==="字符串。然後,從方法內部打印實例。

4

讓我們來找出答案。

class Thing 
    puts "self=#{self}" 
    class << self 
    puts "self in singleton class=#{self}" 
    def foo 
     puts "I am #{self}." 
    end 
    end 
end 
    # self=Thing 
    # self in singleton class=#<Class:Thing> 

Thing.foo 
    # I am Thing. 

我們看到class << self相同class << Thing

這是相同

class Thing 
end 

class << Thing 
    puts "self in singleton class=#{self}" 
    def foo 
    puts "I am #{self}." 
    end 
end 
    # self in singleton class=#<Class:Thing> 

Thing.foo 
    # I am Thing. 

在類中class << selfclass << Thing外部的類做一件事情和只有一兩件事:它隨後的塊內變更selfThing的單例類。這同樣說它會將塊內的範圍更改爲Thing的單例類。

This article by Yehuda Katz is required reading。

+1

值得注意的是'self'指的是上下文中的「Thing」 「類Thing」表達式(並且在方法體的上下文之外)是語言設計目標的直接後果:像attr_reader和include這樣的構造意味着感覺像聲明性關鍵字,但它們被實現作爲'Class'的方法(以及'Module')。爲了感覺聲明性,你希望能夠在類體的上下文中通過純名稱來調用它們。在'self'上調用名字沒有顯式接收者的方法,所以'self'_has_是類。 – philomory

+1

class中的'class << self'或'class <<類外的東西只做一件事,一件事:它將'self'改爲'Thing'的單例類。 - 它還將*默認definee *更改爲'Thing'的單例類,這通常是首要使用它的主要原因。並且它將常量定義上下文更改爲「Thing」的單例類。所以,它確實有三件事情,事實上,「正常」類定義也會改變這三件事。 –

+0

@JörgWMittag,我不熟悉表達式「default definee」。它是爲Ruby定義的嗎?另外,#2和#3從'self'設置爲單例類嗎? –

相關問題