我想了解此代码。为什么它返回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]' –