Import 如何加载实现相同行为的多个模块
我不明白如何使用多个模块,每个模块实现相同的行为,因为我在编译时遇到了这个错误: 函数已从导入 在我的例子中,我有两个模块实现Import 如何加载实现相同行为的多个模块,import,module,erlang,Import,Module,Erlang,我不明白如何使用多个模块,每个模块实现相同的行为,因为我在编译时遇到了这个错误: 函数已从导入 在我的例子中,我有两个模块实现gen_event行为,我正在尝试将它们导入第三个模块中。 每当我试图编译此代码时,都会收到错误消息: -module(mgr). -import(h1,[init/1]). // implements gen_event -import(h2,[init/1]). // implements gen_event 你不能那样做。导入是一个简单的技巧,可以避免编写
gen_event
行为,我正在尝试将它们导入第三个模块中。
每当我试图编译此代码时,都会收到错误消息:
-module(mgr).
-import(h1,[init/1]). // implements gen_event
-import(h2,[init/1]). // implements gen_event
你不能那样做。导入是一个简单的技巧,可以避免编写函数的完整“定义”。它只对编译器说:当您在这个模块中看到
init(P)
时,替换为h1:init(P)
因此,不可能导入具有相同名称/arity的多个函数
对于简短的名称,我认为使用import没有任何好处
如果使用长名称的module:function,并且希望缩短代码中的行,则可以改用宏,并且没有限制(但函数名称与:o相同的可能性也很小):
编辑
下一个示例说明了它的工作原理,首先我创建模块mod1,如下所示:
-module (mod1).
-export ([test/1]).
test(P) ->
case P of
1 -> ok;
2 -> mod2:test()
end.
我在外壳中测试它:
1> c(mod1).
{ok,mod1}
2> mod1:test(1).
ok
3> mod1:test(2).
** exception error: undefined function mod2:test/0
4> % this call failed because mod2 was not defined.
4> % lets define it and compile.
4> c(mod2).
{ok,mod2}
5> mod1:test(1).
ok
6> mod1:test(2).
now it works
ok
7>
mod2创建为:
-module (mod2).
-export ([test/0]).
test() ->
io:format("now it works~n").
在shell中继续:
1> c(mod1).
{ok,mod1}
2> mod1:test(1).
ok
3> mod1:test(2).
** exception error: undefined function mod2:test/0
4> % this call failed because mod2 was not defined.
4> % lets define it and compile.
4> c(mod2).
{ok,mod2}
5> mod1:test(1).
ok
6> mod1:test(2).
now it works
ok
7>
如您所见,无需修改mod1
,只需创建和编译mod2
(请注意,如果mod2已经存在,但功能测试/0未导出,则情况相同)
如果要验证代码是否未使用未定义函数,可以使用外部工具。在使用管理项目时,我使用命令rebar3 xref执行此检查。请注意,调用未定义函数是一个简单的警告,在应用程序升级的上下文中它是有意义的。这种验证不是防弹的:它是在构建时完成的,这并不能保证您需要的模块会在生产系统上以正确的版本出现:它打开了许多关于版本控制、代码加载……的有趣问题。此外,本地函数包装对远程的调用;如果经常使用,可能会从中进行后端口。我认为,当您
导入
时,您也会编译导入的
模块,因此您可以一箭双雕(语言简洁+编译)。因此,如果我的模块Parent
使用了另一个模块Child
我不需要导入它,我可以调用Child:method()
(如果我事先编译子
)?编译中没有顺序。调用在运行时解决:如果被调用的模块没有加载到VM中,它将首先加载它,然后它将查找函数。如果存在,很好,它将执行调用;如果它不存在,然后它将在执行过程中失败。但在我的例子中,问题是我不是使用init
的人。在我的例子中,init被gen\u事件:add\u handler
方法使用。库代码期望目标模块中有init
。在我的例子中,我有多个模块实现gen\u事件
行为,它们都需要公开init
。好的,我在以前的项目中做过这件事,我将尝试检索这个示例并提出一个简化版本。