我想了解这段代码。为什么它会返回Hello
而不是Howdy!
?
class Speaker
@message = "Hello!"
class << self
@message = "Howdy!"
def speak
@message
end
end
end
puts Speaker.speak
答案 0 :(得分:4)
首先,您的消息@message
不是实例变量,或者不是您可能正在考虑的实例变量的类型:它是类级实例var,因此实例变量为{{1} }本身,作为对象是类Speaker
的实例。
这是一个代码版本,用于执行您尝试使用局部变量和闭包执行的操作:
Class
这里有一些代码说明了类级实例变量和“普通”实例变量之间的区别:
class Speaker
@message = "Hello!"
class << self
message = "Howdy!"
define_method(:speak) { message }
end
end
Speaker.speak
#=> "Howdy!"
答案 1 :(得分:3)
这是你的代码,除了我以通常的方式(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!"
通过对比,
@message = "Howdy!"
在Speaker
的单例类上创建一个实例变量:
Speaker.singleton_class.instance_variables
#=> [:@message]
Speaker.singleton_class.instance_variable_get(:@message)
#=> "Howdy!"
现在在speak
上调用Speaker
:
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
答案 2 :(得分:-1)
此代码返回“Hello”的原因是它正在尝试更改类中的实例变量&lt;&lt;自我阻止。
类方法适用于任何不处理该类的单个实例的事物 - 实例变量与类的各个实例相关联,并且我们无法在类级别更改实例变量。
我们应该使用类变量(用@@表示),而不是在speak方法中使用实例变量。
例如,以下代码将返回'你好!' -
class Speaker
@@message = "Hello!"
class << self
@@message = "Howdy!"
def speak
@@message
end
end
end
puts Speaker.speak