元编程Ruby:在class_eval中定义继承

时间:2012-04-04 02:01:33

标签: ruby metaprogramming

我想使用class_eval扩展某些类的功能。我想强制该类从其他类继承一些方法。

即:

SomeClass.class_eval do
  # force inheritence from some other class
end

实现目标的最佳途径是什么?

2 个答案:

答案 0 :(得分:1)

如果在此处覆盖现有功能是一项艰难的要求,则需要在包含的模块中定义现有方法。

class SomeClass
  include DefaultBehaviour
end

module DefaultBehaviour
  def run
    puts "ran default"
  end
end

module AlternateBehaviour
  def run
    puts "ran alternate"
  end
end

SomeClass.class_eval {
  include AlternateBehaviour
}

SomeClass.new.run #=> "ran alternate"

原因是因为ruby的方法查找路径。

它开始于SomeClass - >对象

当您包含AlternateBehaviour时,它会变为SomeClass - > AlternateBehaviour - >宾语。因此,直接在SomeClass上定义的方法仍然优先。

但是,如果在DefaultBehaviour上定义了这些方法,则查找路径将变为SomeClass - > AlternateBehaviour - > DefaultBehaviour - >对象,因此您的备用方法优先。最近包括哪个模块是最高优先级。

如果您无法控制原始班级,则可以改为:

module AlternateBehaviour
  def self.included(base)
    base.send(:remove_method, :run)
  end

  def run
    puts "ran alternate"
  end
end

虽然在这一点上,人们开始怀疑你是否可以通过

做得更好
SomeClass.class_eval {
  def run
    "ran alternate"
  end
end

答案 1 :(得分:0)

尝试使用includeextend,两者都解释了here。他们只使用模块;你只是不能在Ruby创建后修改/添加类的超类。

只有一个问题:您无法覆盖类中已有的方法,而不会在本文的第三条评论中进行说明。

有关详情,请参阅this主题。