Ruby 将构造函数参数转换为实例变量

Ruby 将构造函数参数转换为实例变量,ruby,Ruby,可能重复: 当我有一个initialize方法时,有很多情况如下所示: class Foo def initialize bar, buz, ... @bar, @buz, ... = bar, buz, ... end end class Class def attr_constructor *vars define_method("initialize") do |*vals| vars.zip(vals

可能重复:

当我有一个
initialize
方法时,有很多情况如下所示:

class Foo  
    def initialize bar, buz, ...
        @bar, @buz, ... = bar, buz, ...
    end
end
class Class
    def attr_constructor *vars
        define_method("initialize") do |*vals|
            vars.zip(vals){|var, val| instance_variable_set("@#{var}", val)}
        end
    end
end
class Foo
    attr_constructor :foo, :bar, :buz
end

p Foo.new('a', 'b', 'c')      # => #<Foo:0x93f3e4c @foo="a", @bar="b", @buz="c">
p Foo.new('a', 'b', 'c', 'd') # => #<Foo:0x93f3e4d @foo="a", @bar="b", @buz="c">
p Foo.new('a', 'b')           # => #<Foo:0x93f3e4e @foo="a", @bar="b", @buz=nil>
有没有一种方法可以通过以下简单的命令来实现这一点:

class Foo
    attr_constructor :bar, :buz, ...
end
其中,符号表示实例变量的名称(具有
attr\u accessor
attr\u reader
attr\u writer
)的精神/风格)


我想知道是否有一个内置的方式或更优雅的方式做这样的事情:

class Foo  
    def initialize bar, buz, ...
        @bar, @buz, ... = bar, buz, ...
    end
end
class Class
    def attr_constructor *vars
        define_method("initialize") do |*vals|
            vars.zip(vals){|var, val| instance_variable_set("@#{var}", val)}
        end
    end
end
class Foo
    attr_constructor :foo, :bar, :buz
end

p Foo.new('a', 'b', 'c')      # => #<Foo:0x93f3e4c @foo="a", @bar="b", @buz="c">
p Foo.new('a', 'b', 'c', 'd') # => #<Foo:0x93f3e4d @foo="a", @bar="b", @buz="c">
p Foo.new('a', 'b')           # => #<Foo:0x93f3e4e @foo="a", @bar="b", @buz=nil>
所以我可以这样使用它:

class Foo  
    def initialize bar, buz, ...
        @bar, @buz, ... = bar, buz, ...
    end
end
class Class
    def attr_constructor *vars
        define_method("initialize") do |*vals|
            vars.zip(vals){|var, val| instance_variable_set("@#{var}", val)}
        end
    end
end
class Foo
    attr_constructor :foo, :bar, :buz
end

p Foo.new('a', 'b', 'c')      # => #<Foo:0x93f3e4c @foo="a", @bar="b", @buz="c">
p Foo.new('a', 'b', 'c', 'd') # => #<Foo:0x93f3e4d @foo="a", @bar="b", @buz="c">
p Foo.new('a', 'b')           # => #<Foo:0x93f3e4e @foo="a", @bar="b", @buz=nil>
class-Foo
属性构造函数:foo,:bar,:buz
结束
p Foo.new('a','b','c')#=>#
p Foo.new('a','b','c','d')#=>#
p Foo.new('a','b')#=>#

这对你有用吗

class Foo  
    def initialize(hash)
        hash.each { |k,v| instance_variable_set("@#{k}", v) }
    end
end
我会使用:


有趣的问题。一点元编程就可以了

module Attrs
  def self.included(base)
    base.extend ClassMethods
    base.class_eval do
      class << self
        attr_accessor :attrs
      end
    end
  end

  module ClassMethods
    # Define the attributes that each instance of the class should have
    def has_attrs(*attrs)
      self.attrs = attrs
      attr_accessor *attrs
    end
  end

  def initialize(*args)
    raise ArgumentError, "You passed too many arguments!" if args.size > self.class.attrs.size
    # Loop through each arg, assigning it to the appropriate attribute (based on the order)
    args.each_with_index do |val, i|
      attr = self.class.attrs[i]
      instance_variable_set "@#{attr}", val
    end
  end
end

class Foo
  include Attrs
  has_attrs :bar, :buz
end

f = Foo.new('One', 'Two')
puts f.bar
puts f.buz

这将允许您以任何顺序传递attr,并去除大部分元编程。但是要键入的内容要多得多。

您想在创建过程中初始化属性吗?我想这个问题以前有人问过,但我还没有找到任何完全重复的问题。@Andrewgrim感谢您提到重复的问题。我将在那里看到答案。我会亲自投票结束这件事。这不是我想要的。我希望在类主体中使用一次类方法,它控制
初始化
的行为。在代码中,您需要在构造时指定实例变量的名称,这比在
初始化
方法中仅定义名称更糟糕。编辑看起来非常优雅,但对我来说似乎不起作用。f、 baz etc抛出错误。如果您想让属性在外部可读写,您需要添加attr_访问器,就像正常一样。谢谢您的回答,但是每次都必须写入行
include Attrs
,这似乎让我感到不快。而且,我不一定需要
attr\u访问器
s。