eyw*_*ywu 31 ruby instance-variables attr-accessor attr
我在我的类中动态创建了一个实例变量:
class Mine
attr_accessor :some_var
def intialize
@some_var = true
end
def my_number num
self.instance_variable_set "@my_#{num}", num
end
end
Run Code Online (Sandbox Code Playgroud)
我@my_#{num}
现在如何制作attr值?
例如,我希望能够这样做:
dude = Mine.new
dude.my_number 1
dude.my_1
=> 1
Run Code Online (Sandbox Code Playgroud)
Orl*_*ndo 27
这个答案没有污染类空间,例如..如果我这样做,mine.my_number 4
那么其他实例Mine
将不会得到my_4
方法..这是因为我们使用对象的单例类而不是类.
class Mine
def my_number num
singleton_class.class_eval { attr_accessor "my_#{num}" }
send("my_#{num}=", num)
end
end
a = Mine.new
b = Mine.new
a.my_number 10 #=> 10
a.my_10 #=> 10
b.my_10 #=> NoMethodError
Run Code Online (Sandbox Code Playgroud)
Dor*_*ime 24
这可以使用__send__
.这里:
class Mine
attr_accessor :some_var
def intialize
@some_var = true
end
def my_number num
self.class.__send__(:attr_accessor, "my_#{num}")
self.__send__("my_#{num}=", num)
end
end
dude = Mine.new
dude.my_number 1
puts dude.my_1
=> 1
Run Code Online (Sandbox Code Playgroud)
Ger*_*rry 10
简单.您可以在my_number方法中动态定义属性读取器:
def my_number num
self.instance_variable_set "@my_#{num}", num
self.class.class_eval do
define_method("my_#{num}") { num }
end
end
Run Code Online (Sandbox Code Playgroud)
看看这是否适合你
您可能想要使用 OpenStruct:
require "ostruct"
class Mine < OpenStruct
end
dude = Mine.new
dude.my_number = 1
dude.my_number # => 1
Run Code Online (Sandbox Code Playgroud)
我不知道你为什么要dude.my_1
返回 1 - 这不是把你已经拥有的东西还给你吗?
这里有两个方法存在一个问题......如果在一个实例中设置了一个实例变量,那么它的访问器将可用于所有实例,因为你是在on self.class
而不是在self 上定义方法.
dude = Mine.new
dude.my_number 1
puts dude.my_1
dudette = Mine.new
dudette.my_1 = 2 # works, but probably shouldn't
dudette.my_number 2
dude.my_2 = 3 # works, but probably shouldn't
Run Code Online (Sandbox Code Playgroud)
您可能想要做的是仅修改具有实例变量的实例:
class Mine
# ...
def my_number num
class << self
attr_accessor "my_#{num}"
end
self.send("my_#{num}=", num)
end
end
Run Code Online (Sandbox Code Playgroud)
这样,实例变量只能为它们创建的对象获取访问器.我也没有打扰instance_variable_set,因为如果你正在设置一个访问器,那么我认为重用它会更好.但这是一种风格调用.这里最重要的是打电话class << self
而不是self.class
.