Ruby 为什么extend方法不重视看跌期权

Ruby 为什么extend方法不重视看跌期权,ruby,inheritance,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 我试图做的是从gem截取一个方法的值并做一些事情。我可以使用alias_m

我原以为我会看到的

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

我试图做的是从gem截取一个方法的值并做一些事情。我可以使用alias_method_chain,但我尝试不使用它。

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

在您的例子中,只需调用
Lab.foo
。以下内容(不带
Lab.foo
)将为您提供所需的结果

foo from lab
请注意,
M
的超类是
Module
,由于未定义
Module#foo
,以下内容将导致错误

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

module Lab
  extend M
end

Lab.foo

# => foo from module
如果你在期待

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

module Lab
  extend M
end

Lab.foo

# => method undefined error
然后你需要把super放在Lab#foo里,就像这样:

foo from module
foo from lab

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

因此,直接在
Lab
上定义的
foo
优先于
M#foo
,即使
Lab.extend M

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

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

我删除了我的答案,因为它是不正确的(而且出于某种原因,人们无论如何都在投票)。为了避免人们像我想的那样思考:上面代码中的两个方法都不是实例方法(因为
extend
是如何工作的)。
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