有没有一种干净的方法来删除常见的ruby对象初始化代码?

k97glaaz  于 2021-09-29  发布在  Java
关注(0)|答案(1)|浏览(298)

有没有一种干净的方法来迭代attr_reader属性并设置它们?

class Foo
  attr_reader :bar, :baz, ...

  def initialize attrs
    @bar = attrs[:bar]
    @baz = attrs[:baz]
    .
    .
    .
ocebsuys

ocebsuys1#

如果希望哈希键与属性名匹配,一种可能是继承结构:

class Foo < Struct.new(:bar, :baz, keyword_init: true) # Note the "keyword_init" parameter
end

puts Foo.new(bar: 42, baz: :foo).bar

# => 42

struct还将创建公共编写器,因此如果希望它们不是公共的,则必须将它们设置为私有的

FOO_ATTRS = [:bar, :baz]
class Foo < Struct.new(*FOO_ATTRS, keyword_init: true) # Note the "keyword_init" parameter
  # Make method 'my_attribute=' private if needed
  private *FOO_ATTRS.map { |attr| "#{attr}=" }
end

puts Foo.new(bar: 42, baz: :foo).bar

如果要重命名其他属性名称的哈希键:

class Foo
  INITIAL_ATTRS = {
   foo: :@bar,
   bar: :@baz
  }

  attr_reader *(INITIAL_ATTRS.values.map { |k| k.to_s.delete('@').to_sym })

  def initialize attrs
    attrs.slice(*INITIAL_ATTRS.keys).each do |var, value|
      instance_variable_set(INITIAL_ATTRS[var], value)
    end
  end
end

编辑
另一种可能是使用私有attr_writer,这样就不必处理@tricks

class Foo
  INITIAL_ATTRS = {
   foo: :bar,
   bar: :baz
  }

  attr_reader *(INITIAL_ATTRS.values)

  def initialize attrs
    attrs.slice(*INITIAL_ATTRS.keys).each do |var, value|
      send("#{INITIAL_ATTRS[var]}=", value)
    end
  end

  private

   attr_writer *(INITIAL_ATTRS.values)
end

注意,如果您不想将foo转换为bar,那么可以使用数组而不是散列作为初始属性。这将通过删除 .values.keys ```
class Foo
INITIAL_ATTRS = [:foo, :bar]

attr_reader *INITIAL_ATTRS

def initialize attrs
attrs.slice(*INITIAL_ATTRS).each do |var, value|
send("#{var}=", value)
end
end

private

attr_writer *INITIAL_ATTRS
end

相关问题