Ruby动态对象属性,发送vs实例变量集
假设我有一个简单的对象。我有Ruby动态对象属性,发送vs实例变量集,ruby,metaprogramming,Ruby,Metaprogramming,假设我有一个简单的对象。我有attr\u访问器s用于我想要接受的属性,并且我想要能够使用对象的散列进行初始化: class Example attr_accessor :foo, :bar def initialize( attributes = {} ) attributes.each do |k,v| ... end end end 在上面的attributes.each块中,是否最好使用send,如下所示: send "#{k}=", v in
attr\u访问器
s用于我想要接受的属性,并且我想要能够使用对象的散列进行初始化:
class Example
attr_accessor :foo, :bar
def initialize( attributes = {} )
attributes.each do |k,v|
...
end
end
end
在上面的attributes.each块中,是否最好使用send
,如下所示:
send "#{k}=", v
instance_variable_set "@#{k}".to_sym, v
或者使用实例变量集
,如下所示:
send "#{k}=", v
instance_variable_set "@#{k}".to_sym, v
。。。或者完全做别的事情
我能想到的区别是:
- 如果在某个时候我用setter方法替换了一个
attr\u访问器,那么使用
会更加一致send
- 如果传递了意外值,则使用
将引发send
NoMethodError
send
——我实际上有点喜欢为伪造的init数据而提出NoMethodError
。但是,这里是否还有其他我忽略的因素,特别是性能和安全方面的考虑
我很欣赏你的见解。谢谢 我的答案是使用send
原因:即使访问器不存在,也将使用实例变量集创建实例变量。正如您所提到的,使用send,您将获得一个命名错误。您可以使用
try
而不是send
<如果找不到方法,send
将返回NoMethod错误,try
如果找不到方法将返回nil<代码>尝试不能用于实例方法
示例:
# k is a string or symbol, v a parameter value
try(k)
#=> nil
try(k, v)
#=> nil
但是,应该使用方法instance\u variable\u set
和instance\u variable\u get
示例
# k is a string or symbol, v a value
instance_variable_set("@#{k}", v)
instance_variable_get("@#{k}")
通常的做法是使用send 首先,
instance\u variable\u set
将创建大量额外的实例变量
然后,send使用accessor方法。当其中一个attr访问器被重新定义时,它非常有用,例如:
attr_accessor :foo
def bar=
# something's happening here
end
为了避免出现nomethoder错误
您应该使用respond\u to?
方法:
attributes.each do |k, v|
send("#{k}=", v) if respond_to?(k)
end
也可以在手动初始化或使用gems之前裁剪额外属性,例如
gem'strong_parameters'
我会使用send
,除非我有很好的理由不这样做;一般来说,我更喜欢我的对象在与自己交谈时使用外部接口,这样可以减少维护的麻烦。顺便说一句,如果你不想显式地调用,“@#{k}”
。@muistooshort:谢谢:”
,我不知道!