ruby – 将initialize()args设置为属性的快捷方式?

前端之家收集整理的这篇文章主要介绍了ruby – 将initialize()args设置为属性的快捷方式?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
这是一种常见的初始化模式:
def initialize(title,val,type)
  @title,@val,@type = title,type
end

是否存在等同于“获取每个参数,创建同名属性,并将属性设置为参数值”的快捷方式?

我正在寻找一种无宝石的解决方案.

解决方法

这是你如何做到这一点.将为每个初始化参数创建一个实例变量和一个关联的读/写访问器,变量具有相同的名称,以@开头,并且每个实例变量将被赋予相关参数的值.

class MyClass
  def initialize(< arbitrary parameters >)
    self.class.params.each { |v|
      instance_variable_set("@#{v}",instance_eval("#{v}")) }

    < other code >
  end

  @params = instance_method(:initialize).parameters.map(&:last)
  @params.each { |p| instance_eval("attr_accessor :#{p}") }

  class << self
    attr_reader :params
  end  

  < other code >     
end

class MyClass
  def initialize(a,b,c)
    self.class.params.each { |v|
      instance_variable_set("@#{v}",instance_eval("#{v}")) }
  end

  @params = instance_method(:initialize).parameters.map(&:last)
  @params.each { |p| instance_eval("attr_accessor :#{p}") }

  class << self
    attr_reader :params
  end  
end

MyClass.methods(false)
  #=> [:params]
MyClass.instance_methods(false)
  #=> [:a,:a=,:b,:b=,:c,:c=]

m = MyClass.new(1,2,3)
m.a #=> 1
m.b #=> 2
m.c #=> 3
m.a = 4
m.a #=> 4

说明

解析类MyClass时,为类实例变量@params分配一个数组,其元素是initialize的参数.这是可能的,因为在解析开始@params = …的代码时创建了方法初始化.

方法Method#parameters用于获得初始化的参数.对于上面的例子,

instance_method(:initialize).parameters
  #=> [[:req,:a],[:req,:b],:c]]

所以

@params = instance_method(:initialize).parameters.map(&:last)
  #=> [:a,:c]

然后我们创建读/写访问器:

@params.each { |p| instance_eval("attr_accessor :#{p}") }

和@params的读访问器,供初始化使用:

class << self
  attr_reader :params
end

创建MyClass的实例my_class时,传递给MyClass.new的参数值将传递给initialize.通过类实例变量@params初始化然后循环并设置每个实例变量的值.在这个例子中,

MyClass.new(1,3)

调用initialize(a,c)where

a => 1
b => 2
c => 3

我们有:

params = self.class.params
  #=> [:a,:c]

params.each { |v| instance_variable_set("@#{v}",instance_eval("#{v}")) }

对于params的第一个元素(:a),这是:

instance_variable_set("@a",instance_eval(a) }

这是:

instance_variable_set("@a",1 }

导致@a被分配1.

请注意@params的访问器不是必需的:

class MyClass
  def initialize(a,c)
    self.class.instance_variable_get(:@params).each { |v|
      instance_variable_set("@#{v}",instance_eval("#{v}")) }
  end

  @params = instance_method(:initialize).parameters.map(&:last)
  @params.each { |p| instance_eval("attr_accessor :#{p}") }
end

猜你在找的Ruby相关文章