1

I'd like to write something like that :

class Test
  def initialize(a,b,c)
  end

  def print()
    puts @a
    puts @b
    puts @c
  end
end

Test.new({a=>1, b=>2, c=>3}).print()
=>1
=>2
=>3

Is there a way to instanciate an object and map its parameters with an hash table?

Thanks in advance.

4

3 回答 3

4
class Test
  def initialize(options)
    options.each do |key, value|
      instance_variable_set("@#{key}", value)
    end
  end

  def print
    puts @a
    puts @b
    puts @c
  end
end

Test.new(:a => 1, :b => 2, :c => 3).print

或使用OpenStruct

http://www.ruby-doc.org/stdlib-1.9.3/libdoc/ostruct/rdoc/OpenStruct.html

这是一个简单的例子:

require 'ostruct'

puts OpenStruct.new(:a => 1, :b => 2, :c => 3).inspect
# Outputs: "#<OpenStruct a=1, b=2, c=3>"
于 2013-08-07T17:14:02.023 回答
4

如果您仍在使用 Ruby 1.9.3,您可以很容易地使用 Hash 对象:

class Test
  attr_accessor :a, :b, :c

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

  def print()
    puts @a
    puts @b
    puts @c
  end
end

Test.new( {:a => 1, :b => 2, :c => 3}).print()
# 1
# 2
# 3
# => nil

但是请记住,如果它不匹配a,它将创建一个变量,称为您作为键传递的任何内容b,否则c您的访问器将失败。

于 2013-08-07T17:14:29.843 回答
3

当前版本的 Ruby 中,您可以使用关键字参数:

def initialize(a: nil, b: nil, c: nil)
  @a, @b, @c = a, b, c
end

请注意,目前,关键字参数始终具有默认值,因此始终是可选的。如果你想强制关键字参数,你可以使用默认值可以是任何Ruby 表达式的简单技巧:

def mand(name) raise ArgumentError, "#{name} is mandatory!" end

def initialize(a: mand 'a', b: mand 'b', c: mand 'c')
  @a, @b, @c = a, b, c
end

在 Ruby 的下一个版本中,可以通过省略默认值来强制使用关键字参数:

def initialize(a:, b:, c:)
  @a, @b, @c = a, b, c
end

看这里:

class Test
  def initialize(a:, b:, c:)
    @a, @b, @c = a, b, c
  end

  def to_s
    instance_variables.map {|v| "#{v} = #{instance_variable_get(v)}" }.join("\n")
  end
end

puts Test.new(a: 1, b: 2, c: 3)
# @a = 1
# @b = 2
# @c = 3
于 2013-08-07T23:35:07.703 回答