这里是来自about_classes.rb的代码。我不确定答案为何[ ]
和[:@name]
class Dog2
def set_name(a_name)
@name = a_name
end
def test_instance_variables_can_be_set_by_assigning_to_them
fido = Dog2.new
assert_equal [ ], fido.instance_variables
#In this case, fido doesn't have any instance_variables,
because it is assigned to a new "Dog2" Hash/class which has none methods?
fido.set_name("Fido")
assert_equal [:@name], fido.instance_variables
#In this case, fido has an instance_variable,
because it uses the set_name methods inherited from "Dog2" classes?
end
assert_raise(SyntaxError) do
eval "fido.@name"
# NOTE: Using eval because the above line is a syntax error.
end
#So Eval here means that if the above returns "fido.@name", give it a SyntaxError?
我在这2个案例中添加了一些评论,看看我是否理解正确。
答案 0 :(得分:2)
当第一个assert_equal
被调用时,Dog2
实例(fido
)没有实例变量,因为没有在初始化程序中或以任何其他方式定义。
当set_name
被调用时,@name
实例变量被设置,所以当第二个assert_equal
被调用时,fido
实例会有一个实例变量,一个,@name
,所以fido.instance_variables
方法返回一个带有那个符号的数组。
回答您在代码示例中的评论中提出的问题:
不,你的前两条评论不准确。这不是因为它没有方法,而是因为它没有实例变量。 fido
实例确实有一个方法set_name
方法。
您的第二条评论不准确,因为此处没有继承,fido
是Dog2
的实例,因此一旦调用set_name
方法,它就具有实例变量,因为@name
方法初始化了set_name
。
关于eval
的最终评论/问题仅仅是因为如果作者实际上只编写了fido.@name
,那么代码本身就无法运行,他们希望它能够运行但是显示如果您在代码中写了fido.@name
,那么由于语法错误,Ruby会退出并拒绝运行您的代码。
来自OP的另一个问题我想添加,虽然@name
方法中存在set_name
,但这个例子的真正意义在于,在set_name
之前显示称@name
变量尚未存在。在其他语言中,您可以预先定义所有实例变量,因此它们始终存在于该类的任何实例化对象中。
Ruby是一种更加动态的语言,因此在实际执行@name = a_name
代码行之前,@name
变量不存在,因此不会在fido.instance_variables
中返回
即使调用该方法也是如此,但@name = a_name
行未被执行,例如。
class Dog2
def set_name a_name
if false
@name = a_name
end
end
end
fido = Dog2.new
fido.set_name "Fido"
fido.instance_variables # => []
希望有所帮助。