我是Ruby的新手并且对如何在Class
中创建类似于:attr_accessor
的方法感到困惑,因为它将方法添加到用户类,但是这些添加的方法可以访问预初始化的实例变量。我很难解释,所以这里有一个非常简化的我的努力样本:
class Class
def super_accessor_wow(attr_name)
attr_name = attr_name.to_s
new_var_name = "@crazy_var_name"
instance_variable_set(new_var_name, ["hi", "everyone"])
module_eval(%Q/
def super_#{attr_name}()
return @#{attr_name}
end
def super_#{attr_name}=(value)
@#{attr_name} = value
end
def greetings
return #{new_var_name}
end
/)
end
end
这就是我试图在Class
上使用新方法修改我自己的类的方法:
class Foo
super_accessor_wow(:bar)
end
foo1 = Foo.new()
foo1.super_bar = 1000
puts foo1.super_bar
puts foo1.greetings.inspect
第一个放置印刷品'1000'
第二个会打印'nil'
,因此instance_variable_set
中的super_accessor_wow
来电似乎无效。
顺便说一下,我预计第二次看跌会打印'['hi', 'everyone']'
。所有这些代码都包含在一个Ruby文件中。
答案 0 :(得分:1)
在课程定义期间致电instance_variable_set
时,系统会调用super_accessor_wow
。目前还没有该类的实例。您在调用new
时创建该类的实例。您可以将@crazy_var_name
初始化添加到构造函数中,也可以使用greetings
方法定义它:
将默认值放在类变量中,并在构造函数中初始化实例变量(请注意,这会为您的类创建一个构造函数,如果您创建自己的构造函数,它将覆盖此变量):
class Class
def super_accessor_wow(attr_name)
attr_name = attr_name.to_s
new_var_name = "@crazy_var_name"
new_var_name_default = "@#{new_var_name}"
module_eval(%Q/
#{new_var_name_default} = ["hi", "everyone"]
def initialize()
#{new_var_name} = #{new_var_name_default}
end
def super_#{attr_name}()
return @#{attr_name}
end
def super_#{attr_name}=(value)
@#{attr_name} = value
end
def greetings
return #{new_var_name}
end
/)
end
end
class Foo
super_accessor_wow(:bar)
end
foo1 = Foo.new()
foo1.super_bar = 1000
puts foo1.super_bar
puts foo1.greetings.inspect
puts Foo.class_variable_get('@@crazy_var_name').inspect
puts foo1.instance_variable_get('@crazy_var_name').inspect
输出:
1000
["hi", "everyone"]
["hi", "everyone"]
["hi", "everyone"]
在greetings
方法中定义:
class Class
def super_accessor_wow(attr_name)
attr_name = attr_name.to_s
new_var_name = "@crazy_var_name"
module_eval(%Q/
def super_#{attr_name}()
return @#{attr_name}
end
def super_#{attr_name}=(value)
@#{attr_name} = value
end
def greetings
#{new_var_name} = ["hi", "everyone"] unless #{new_var_name}
return #{new_var_name}
end
/)
end
end
class Foo
super_accessor_wow(:bar)
end
foo1 = Foo.new()
foo1.super_bar = 1000
puts foo1.super_bar
puts foo1.greetings.inspect
输出
1000
["hi", "everyone"]
答案 1 :(得分:0)
如评论中所述,instance_variable_set采用符号,而不是字符串,因此我们将首先修复它。
instance_variable_set(new_var_name.to_sym, ["hi", "everyone"])
但是最大的问题是instance_variable_set没有被Foo实例调用,它被Foo类本身调用。因此,正在设置实例变量,但不是您所期望的。
Foo.instance_variable_get(:@crazy_var_name).inspect
# ["hi", "everyone"]