我正在使用第三方开源库。
在库中,有一个文件( Aaa-Bbb / Ccc.rb )的代码如下所示:
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)
为什么呢?如何解决这个问题?
答案 0 :(得分:0)
您需要在自己的模块中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
答案 1 :(得分:0)
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
后,它会首先搜索模块get_data
中的MyMod
方法,但没有一个方法。因此,它会在顶级对象(模块)中搜索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
已在先前已加载的代码中定义。