为什么扩展方法不是放置值

时间:2011-06-13 22:22:00

标签: ruby inheritance

module Lab
  def self.foo
    puts 'foo from lab'
  end
end

module M
  def foo
    puts 'foo from module'
    super
  end
end

module Lab
  extend M
end

Lab.foo

我原以为我会看到

foo from module
foo from lab

然而,我得到的是

foo from lab

我想要做的是从gem中截取方法的值并做一些事情。我可以使用alias_method_chain,但我不想使用它。

3 个答案:

答案 0 :(得分:1)

如果你期待

foo from module
foo from lab

然后你需要将 super 放在Lab#foo中,如下所示:

module Lab
  def self.foo
    super
    puts 'foo from lab'
  end
end

module M
  def foo
    puts 'foo from module'
  end
end

module Lab
  extend M
end

Lab.foo

答案 1 :(得分:1)

Lab上定义的方法直接优先于M扩展的Lab等模块中定义的方法。

所以直接在foo上定义的Lab优先于M#foo,即使是Lab.extend M

要获得您想要的,请执行以下操作:

module Lab
  module HasFoo
    # foo isn't defined directly on Lab directly anymore;
    # instead, it is defined in a separate module that
    # Lab extends
    def foo
      puts "foo from lab"
    end
  end

  extend HasFoo
end

module M
  def foo
    puts "foo from module"
    super
  end
end

module Lab
  # when Lab extends another module with foo, that changes
  # which concrete method the name foo gets resolved to
  extend M
end

# now you should see the module foo and then the lab foo
Lab.foo

答案 2 :(得分:0)

当您将模块M包含/扩展到类C时,并调用也为C#method定义的方法C.methodM,然后C在方法的搜索路径中优先于M。换句话说,您不能通过include / extend覆盖方法。您只能添加新方法。请参阅this相关问题。

在您的情况下,简单地调用Lab.foo。以下(没有Lab.foo)将为您提供所需的结果。

module M
  def foo
    puts 'foo from module'
  end
end

module Lab
  extend M
end

Lab.foo

# => foo from module

请注意,您的M的超类是Module,由于未定义Module#foo,因此以下内容会导致错误。

module M
  def foo
    puts 'foo from module'
    super
  end
end

module Lab
  extend M
end

Lab.foo

# => method undefined error