在ruby中创建泛型构造函数

时间:2013-07-17 21:21:19

标签: ruby

我找到了这个有趣的答案:

https://stackoverflow.com/a/2348854/169277

当您尝试设置实例变量时,这很好。

有没有办法应用相同的逻辑或更好的逻辑来创建通用构造函数,如:

def initialize(obj)
  obj.each do |k,v|
   #find the setter for each k and set the value v to and return newly created object
  end
end

如果我有对象TestObject

class TestObject
attr_accessor :name, :surname, :sex
end

我正在考虑创建这样的东西:

TestObject.new({:name => 'Joe', :surname => 'Satriani'})

如何实现这一目标?

这样做可以简写:

t = TestObject.new
t.name = 'Joe'
t.surname = 'Satriani'

3 个答案:

答案 0 :(得分:1)

当然,您可以使用send向对象发送任意消息。由于我们在此处self进行操作,因此我们可以直接调用send

def initialize(obj)
  obj.each do |k,v|
    send(:"#{k}=", v)
  end
end

例如,TestObject.new({:name => 'Joe'})会调用send "name=", "Joe"

答案 1 :(得分:1)

您可以从Struct继承以创建一个简单对象,然后将属性传递给初始化程序:

class TestObject < Struct.new(:name, :surname, :sex)
end

TestObject.new('Joe', 'Satriani') #=> sex will be nil

您可以使用OpenStruct制作具有任意属性的快速值对象:

t = OpenStruct(name: 'Joe', surname: 'Satriani')

您可以添加像Virtus这样的模块:https://github.com/solnic/virtus

或者你可以做Chris Heald所说的。

答案 2 :(得分:0)

我认为最好使用关键字参数。毕竟,Hash密钥保证是有效的Ruby标识符Symbol,因为它们需要与方法名称匹配。您不需要将任意Ruby对象作为Hash的键传递。

def initialize(**attrs)
  attrs.each do |attr, value| send(:"#{attr}=", value) end
end

TestObject.new(name: 'Joe', surname: 'Satriani')