红宝石 – 抽象初始化属性的最佳方式

前端之家收集整理的这篇文章主要介绍了红宝石 – 抽象初始化属性的最佳方式前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
抽象这种模式的最佳方法是什么?
class MyClass
  attr_accessor :foo,:bar

  def initialize(foo,bar)
    @foo,@bar = foo,bar
  end
end

一个好的解决方案应该考虑超类,并能够处理仍然能够有一个初始化器来做更多的事情.额外的积分,不会牺牲您的解决方案的性能.

解决方法

这个问题的解决方案已经(部分) exists,但是如果你想在你的类中使用更多的声明性方法,那么下面的代码应该是可行的.
class Class
  def initialize_with(*attrs,&block)
    attrs.each do |attr|
      attr_accessor attr
    end
    (class << self; self; end).send :define_method,:new do |*args|
      obj = allocate
      init_args,surplus_args = args[0...attrs.size],args[attrs.size..-1]
      attrs.zip(init_args) do |attr,arg|
        obj.instance_variable_set "@#{attr}",arg
      end
      obj.send :initialize,*surplus_args
      obj
    end
  end
end

你现在可以做到:

class MyClass < ParentClass
  initialize_with :foo,:bar
  def initialize(baz)
    @initialized = true
    super(baz) # pass any arguments to initializer of superclass
  end
end
my_obj = MyClass.new "foo","bar","baz"
my_obj.foo #=> "foo"
my_obj.bar #=> "bar"
my_obj.instance_variable_get(:@initialized) #=> true

这个解决方案的一些特点:

>使用initialize_with指定构造函数属性
>可以使用initialize来进行自定义初始化
>可能在初始化时调用super
>初始化的参数是由initialize_with指定的属性未被消耗的参数
>轻松地提取到模块中
>使用initialize_with指定的构造方法属性是继承的,但是在子类上定义新集合将删除属性
>动态解决方案可能有性能下降

如果要创建具有绝对最低性能开销的解决方案,将大多数功能重构为字符串并不难,可以在定义初始化程序时对其进行评估.我没有将差异作为基准.

注意:我发现黑客新作比黑客入侵初始化更好.如果使用元编程定义initialize,则可能会得到一个方法,您将一个块传递给initialize_with作为替代初始化程序,并且不可能在块中使用super.

猜你在找的Ruby相关文章