我想了解此代碼。爲什麼它返回Hello
而不是Howdy!
?類方法正在訪問實例變量
class Speaker
@message = "Hello!"
class << self
@message = "Howdy!"
def speak
@message
end
end
end
puts Speaker.speak
我想了解此代碼。爲什麼它返回Hello
而不是Howdy!
?類方法正在訪問實例變量
class Speaker
@message = "Hello!"
class << self
@message = "Howdy!"
def speak
@message
end
end
end
puts Speaker.speak
此代碼返回「你好」的原因是,它正試圖在一個類< <自身塊來改變一個實例變量。
類方法適用於任何不處理該類的單個實例的任何事物 - 實例變量與類的各個實例相關聯,並且我們無法在類級別更改實例變量。
而不是在說方法中使用實例變量,我們應該使用類變量(用@@表示)。
作爲一個例子,下面的代碼將返回'你好!' -
class Speaker
@@message = "Hello!"
class << self
@@message = "Howdy!"
def speak
@@message
end
end
end
puts Speaker.speak
首先,你的消息@message
不是一個實例變量,或者更確切地說,沒有實例變量,你可能會思考型:這是一個類級別的實例變種,所以Speaker
本身就是一個實例變量,其作爲對象是類Class
的實例。
下面的代碼的版本,那麼你想要什麼有局部變量和閉合的事情:
class Speaker
@message = "Hello!"
class << self
message = "Howdy!"
define_method(:speak) { message }
end
end
Speaker.speak
#=> "Howdy!"
,這裏是一些代碼,說明類級別的實例變量之間的差異一個「正常」的實例變量:
class Speaker
@message = 'Howdy!' # class-level instance variable
def initialize
@message = 'Hello!' # instance variable of Speaker's instances
end
def speak
@message
end
class << self
def speak
@message
end
end
end
Speaker.speak
#=> "Howdy!"
Speaker.new.speak
#=> "Hello!"
這裏是你的代碼,但我已經定義通常的方式(def self.speak...
)類方法。由於類方法不過是在類的單例類上定義的實例方法,所以這種更改僅僅是創建相同類方法的不同方式。 (如果你懷疑這種情況,請在兩種方式下運行代碼。)我做了這個改變,因爲我認爲這會讓我解釋清楚的事情。我還添加了一個puts
聲明。
class Speaker
@message = "Hello!"
def self.speak
puts "self=#{self}"
@message
end
class << self
@message = "Howdy!"
end
end
類定義的第一行創建一個類的實例變量@message
:
Speaker.instance_variables
#=> [:@message]
Speaker.instance_variable_get(:@message)
#=> "Hello!"
通過constrast,
@message = "Howdy!"
上創建Speaker
的單件類的一個實例變量:
Speaker.singleton_class.instance_variables
#=> [:@message]
Speaker.singleton_class.instance_variable_get(:@message)
#=> "Howdy!"
現在在Speaker
調用speak
:
Speaker.speak
# self=Speaker
#=> "Hello!"
由於self #=> Speaker
,speak
顯然是返回類實例變量的值。
對於speak
返回上Speaker
的單個類中定義的實例變量的值,我們可以寫出如下:
class Speaker
@message = "Hello!"
def self.speak
puts "self=#{self}"
puts "singleton_class = #{singleton_class}"
singleton_class.instance_variable_get :@message
end
class << self
@message = "Howdy!"
end
end
puts Speaker.speak
# self=Speaker
# singleton_class = #<Class:Speaker>
# Howdy!
在最後一個表達式,因爲self
等於Speaker
和self
是隱含的接收器時沒有明確的接收方,"singleton_class
相當於Speaker.singleton_class
。
上面的'@ message'是一個類級別的實例變量,它屬於'Speaker'類,它本身作爲一個對象是類'Class'的一個實例:'Speaker.class#=> Class','Speaker .instance_variables#=> [:@message]' –