我正在使用一个第三方开源库。
在库中,有一个文件(Aaa-Bbb/Ccc.rb)'s代码如下所示:
module Aaa
module Bbb
module Ccc
def get_data
...
end
end
end
end在我的Ruby项目中,我需要从上面的模块调用get_data方法。所以我试了一下:
require 'Aaa-Bbb/Ccc'
module MyMod
def my_func
# Error: undefined method 'get_data' for MyMod:Module (NoMethodError)
data = get_data
end
end当我运行以上代码时,会得到错误:
undefined method 'get_data' for MyMod:Module (NoMethodError)为什么?如何解决这个问题?
发布于 2016-09-12 13:03:52
您需要在自己的模块中include所需的模块:
require 'Aaa-Bbb/Ccc'
module MyMod
# Including the required module to make all its methods available here.
include Aaa::Bbb::Ccc
def my_func
data = get_data
end
end发布于 2016-09-13 03:44:45
require将在解释器的当前实例中处理给定的文件,但对当前命名空间没有任何影响。使用include将方法从另一个名称空间导入到当前命名空间中;请注意,include不读取文件,也不与文件有任何其他关联。
所以,如果你开始
require 'Aaa-Bbb/Ccc'
module MyMod
def self.my_func; data = get_data; end
end(请注意,我在函数名前面添加了一个self.,因为我假设从示例的性质来看,这里不使用对象。)
在处理require方法之后,解释器已经处理了等效的
module Aaa; module Bbb; module Ccc
def self.get_data; ...; end
end; end; end
module MyMod
def self.my_func; data = get_data; end
end这定义了两个方法,其完全限定名为Aaa::Bbb::Ccc::get_data和MyMod::my_func。当my_func被执行时,它将首先在模块MyMod中搜索一个get_data方法,但是没有。因此,它将在顶层对象(模块)中搜索一个get_data方法,如果没有在那里找到它,那么NoMethodError异常就会失败。
有两种方法可以在其他模块中查看,而不是直接在您的模块上查找该方法。首先,您可以使用完全限定的名称直接调用它:
data = ::Aaa::Bbb::Ccc::get_data其次,您可以使用include将来自另一个模块的所有方法带到您自己模块的命名空间中:
include ::Aaa::Bbb::Ccc
data = get_data您将注意到,我在上面的示例中使用了一个初始的::来强制搜索Aaa从顶层的对象/模块开始。在这个简单的示例中,这不是必要的,但是在处理深度嵌套的模块时,这通常是一个很好的实践,因为如果您正在嵌套,比如
module Xxx; module Aaa; module MyMod
def self.my_func; ...; end
end; end; end只使用Aaa而不是::Aaa就可以找到封装的::Xxx::Aaa模块,而不是顶级的::Aaa模块。
还请注意,在进行深度嵌套时,使用
module Aaa::Bbb::Ccc; module Ddd
def self.f; ...; end
end; end为了节省嵌套和module/end的使用,您确实需要确保在上述情况下,已经在加载的前面代码中定义了模块Aaa和Aaa::Bbb。
https://stackoverflow.com/questions/39450920
复制相似问题