为什么在ruby中无法访问同一模块中的功能?

时间:2012-03-23 16:11:48

标签: ruby module

假设我们的代码看起来像这样

module TM
  def aa
    puts "aa"
  end

  def bb
    TM::aa
  end

  module_function :bb
end

TM.bb

为什么bb无法通过“TM :: aa”,“self.aa”或“TM.aa”访问aa?它们属于同一模块。设置此类限制有什么好处?如何解决“未定义方法”错误?

4 个答案:

答案 0 :(得分:4)

你的意思是这样吗?

module TM
  class << self
    def aa
      puts "aa"
    end

    def bb
      TM::aa
    end
  end
end

TM.bb

更新您定义它们的方法可以作为实例方法在include您的模块或类方法时extend您的类

module TM
  def aa
    puts "aa"
  end

  def bb
    aa
  end
end

class A
  include TM
end

class B
  extend TM
end

A.new.bb

B.bb

答案 1 :(得分:1)

因为aa是一个实例函数。如果将其添加到module_function列表中(或使用声明模块方法的许多其他方法之一),一切正常。就个人而言,我更喜欢:

module TM
  def self.aa
    puts "aa"
  end

  def self.bb
    TM::aa
  end

end

TM.bb

答案 2 :(得分:1)

这不起作用,因为您正在定义实例方法(def aa)而不是模块方法(def self.aa)。

查看文档:

  

模块是方法和常量的集合。模块中的方法可以是实例方法或模块方法。当包含模块时,实例方法在类中显示为方法,而模块方法则不包括。相反,可以在不创建封装对象的情况下调用模块方法,而实例方法则可以不调用。 (参见Module#module_function)

所以你想要的可能是:

module TM
  def self.aa
    puts "aa"
  end

  def bb
    TM::aa
  end

  module_function :bb
end

TM.bb

答案 3 :(得分:1)

我认为你可能会对调用module_function的功能感到困惑,因为这个方法实际上创建了方法的副本并使原始方法变为私有,并将副本混合到元类(或任意类中)案例一步进入方法查找链)。这样就可以在不影响方法的内部使用的情况下覆盖它,即使其在私人使用时安全,同时也可公开使用或公开覆盖。它只是复制到无法访问aa的元类中的副本,因为它在查找链中不存在于其上方。如果两个方法都传递给模块函数,那么您将无法获得未定义的方法错误。