使用其他数据动态创建类方法:数据丢失

时间:2013-11-26 09:55:30

标签: ruby

我有一个类,它由另一个类的方法动态扩展。这些方法中还有一些额外的静态信息,例如: G:

class A
  # @b = B.new # in initialize
  def a
    puts @b.info[:data][__callee__]
  end
end

class B
  attr_reader :info
  @info = {:data => {:a => :method_name, …}} 

  def define_new_a name
    A.class_eval %Q(
      alias_method name, :a
    )
    @info[:data][name => :method_name]
  end

  define_new_a :a1
  define_new_a :a2
end

此别名方法:a1以某种方式依赖于@info结构(A中的代码使用B#info[:data])。 @info也可能在执行期间更新。在我第二次(第三次,第四次等)时间调用A.new之前,一切都很完美。在这种情况下,我已经使用方法更新了A类定义,例如:a1:a2(动态创建),但是B#info的纯粹新实例。

所以,问题是:

TL; DNR 我们的class定义可能会发生变化:需要动态添加方法相关数据。类实例是在长期内创建的。有没有办法使用相关数据进行当前类定义 synchronized

说明: 其中我应该存储一些其他信息,例如info结构,以使其与当前定义同步A班的?使B成为单身并不是一个选项,而是使@@info成为一个类变量,因为它可能在A的不同实例之间实际上有所不同。实际上,为了澄清问题,引入了两个类;可能有一个类同时具有a)动态创建的方法和b)一些额外的信息,这些方法依赖于。带有散列instance ⇒ info的单身人士看起来有点多余而且完全不优雅。

另一个问题是是否有一种简单的方法来实例化版本的,而没有任何动态创建(在当前长期运行中)的东西?

提前致谢。

1 个答案:

答案 0 :(得分:1)

当您的B级加载时,您在A上调用class_eval两次以定义两种新方法。

所以没有:一旦加载了B的定义,A的定义就会不可逆转地改变,你就无法再访问它的原始定义了。

您可以做的解决方法是将A打包到一个类中,以保持原始功能的完整性:

class AFresh
  # Your code
end

class A < AFresh
  # Just inherit...
end

顺便说一下:你的设计似乎是依赖注入模式的一个非常破碎的变化。如果是,请查看Symfony的依赖注入组件,以获得如何正确执行此操作的极好示例。然后研究Ruby的内置Forwardable模块。