作为Ruby元编程的一个实验,我可以说我有一个类Pet
,它带有几个关键字参数。
然后我想动态地将关键字参数分配给属性:
class Pet
def initialize(name:, age: 0)
args = method(__method__).parameters.map { |arg| arg[1] }
args.each do |name|
instance_variable_set("@#{key.to_s}", eval(name.to_s)) # Is it possible to do this without eval?
end
end
end
但我想避免使用eval
。
是否可以使用Javascript中的arguments
对象来获取调用函数的参数?
修改:
为何选择关键字参数?这里的想法是在initializer
声明中指定allowed和default参数。虽然可能不是世界上最好的想法,但是因为你可以在不使用docblock的IDE检查中获得签名,所以它会很酷。
请注意:我非常清楚这可以通过使用splat
或hash
作为参数来实现。这不是问题。
答案 0 :(得分:1)
您可以使用eval
名义上避免使用binding.local_variable_get
,这听起来就像听起来一样。
class Pet
def initialize(name:, age: 0)
args = method(__method__).parameters.map { |arg| arg[1] }
args.each do |name|
instance_variable_set(:"@#{name}", binding.local_variable_get(name))
end
end
end
当然,如果你只是哈希,这会变得更加清晰。界面相同;来电者仍然可以Pet.new(name: 'Rover', age: 5)
。
答案 1 :(得分:1)
关键字参数作为局部变量添加,因此,您可以使用当前binding
获取值:
class Pet
def initialize(name:, age: 0)
args = method(__method__).parameters.map { |arg| arg[1] }
args.each do |key|
value = binding.local_variable_get(key)
instance_variable_set("@#{key}", value)
end
end
end
但有些警告适用。使用binding
,您可以访问有关特定变量范围的详细信息。虽然这是强大的,但它在Ruby中通常相当慢,事实上,支持binding
根本就是所有Ruby实现中最伟大的性能杀手之一。
此外,以这种方式访问本地变量可能会导致严重的安全问题,因为它可用于访问不相关的系统状态。要非常小心,你用这种方式暴露哪些变量。
最后,绑定总是在调用它的确切位置生成。这意味着,如果您将新值分配给例如调用name
之前的binding
变量,它将返回该新值,而不是原始方法参数。因此,我将您的块参数名称更改为key
。