我有以下代码,我手动设置attr_reader
和attr_writer
。
class Pairs
attr_reader :pair, :asks, :bids, :isFrozen, :seq, :main_currency, :sub_currency
attr_writer :pair, :asks, :bids, :isFrozen, :seq
def initialize (key, args)
@pair = key
@main_currency, @sub_currency = key.split('_')
args.each {|k,v|
if numeric?(v) then v=v.to_f end
self.instance_variable_set("@#{k}".to_sym, v)
}
end
private
def numeric?(string)
Float(string) != nil rescue false
end
end
有没有办法根据参数的键自动设置它们,比如我自动用@k
填充v
?我可以为每个attr_reader
设置@k
吗?
我想这样的事情:
self.attr_reader("@#{k}")
对于班级的所有对象,甚至更好,例如:
Pairs << attr_reader("@#{k}")
答案 0 :(得分:1)
我怀疑我理解了这个问题,但是从我得到的内容来看,你希望在运行时使用属性读取器动态扩展你的类。
这种方法可以:
def extend_self_with_reader name
self.class.send :attr_reader, name
end
测试:
class C
def extend_self_with_reader name
self.class.send :attr_reader, name
end
def initialize *keys
puts keys.inspect
keys.each(&method(:extend_self_with_reader))
end
end
cc = C.new(*%i|a b c|)
cc.a #⇒ nil
答案 1 :(得分:1)
我将假设您可能正在使用针对不同keys
的许多Hash
来创建此项,如果是这种情况,则不要使用不需要的读者将各个实例混为一起,以便存在不存在的键#&# 39;为此使用singleton_class
。
所以你的最终Pairs
课程看起来像
class Pairs
attr_reader :main_currency, :sub_currency
attr_accessor :pair, :asks, :bids, :isFrozen, :seq
def initialize (key, args)
@pair = key
@main_currency, @sub_currency = key.split('_')
args.each do |k,v|
singleton_class.send(:attr_reader,k)
instance_variable_set("@#{k}", convert_numeric(v))
end
# Alternatively:
# args.each do |k,v|
# val = convert_numeric(v)
# define_singleton_method(k) {val}
# end
end
private
def convert_numeric(val)
Float(Rational(val)) rescue val
end
end
<强> TL; DR 强>
例如:(使用@ mudasobwa&#39; s方法)
class C
def extend_self_with_reader name
self.class.send :attr_reader, name
end
def initialize *keys
keys.each(&method(:extend_self_with_reader))
end
end
这会导致后续读者混淆实例并在实例之间出血:
a = C.new(:a,:b)
a.a #=> nil
b = C.new
b.a #=> nil
c = C.new(:r)
c.a #=> nil
c.r #=> nil
a.methods.sort - Object.methods
#=> [:a, :b, :extend_self_with_reader, :r]
a.r #=> nil (hmmmmm)
而是使用实例的singleton_class
来本地化这些读者,例如:
class C
def initialize *keys
singleton_class.send(:attr_reader, *keys)
end
end
然后
a = C.new(:a,:b)
a.a #=> nil
b = C.new
b.a #=> NoMethodError: undefined method `a'
c = C.new(:r)
c.a #=> NoMethodError: undefined method `a'
c.r #=> nil
a.r #=> NoMethodError: undefined method `r'
a.methods.sort - Object.methods
#=> [:a,:b]
b.methods.sort - Object.methods
#=> []
使用singleton_class
将这些读者本地化为对象的实例,而不是将它们放入Class
定义中。如果attr_reader
不是必需条件,那么这也足够了:
keys.each {|k| define_singleton_method(k) {}}
答案 2 :(得分:0)
或许关注define_method
。
我不是100%确定我理解这个问题,但请检查一下:
hash = { a: 1, b: 2, c: 3 }
hash.keys.each do |key|
define_method(key) do
hash[key]
end
end
现在有a,b和c的方法:
a => 1
b => 2
c => 3
这实际上为哈希中的所有键创建了attr_reader
。您可以为attr_writer
执行类似操作。