我将以最小的例子解释我的问题。假设我有三个文件:
A.jl
module A
export Atype, f
type Atype
end
f = function(x::Atype)
println("f called with A")
end
end #module
B.jl
module B
export Btype, f
type Btype
end
f = function(x::Btype)
println("f called with B")
end
end #module
Main.jl
using A
using B
main = function()
x = Atype()
f(x)
end
main()
这里我有两个版本的f
函数。如果我理解正确的多次发送的想法,应该在运行时期间扣除应该使用哪个版本。因此,我预计运行Main.jl会打印f called with A
。不幸的是,我得到了
$ julia Main.jl
ERROR: type: anonymous: in typeassert, expected Btype, got Atype
in include at /usr/bin/../lib64/julia/sys.so
in process_options at /usr/bin/../lib64/julia/sys.so
in _start at /usr/bin/../lib64/julia/sys.so
while loading /home/grzes/julia_sucks/Main.jl, in expression starting on line 9
如果我评论using B
,它就可以了。很明显,来自B.jl的f
覆盖了来自A.jl的f
。
所以,问题是:问题出在哪里?在我的方法或Julia的版本中,我使用(0.3.7)?我怎么能绕过这个?
请注意,将using A
替换为import A
并使用完全限定名称(例如A.f
)并不是一个好方法。它与多次发送的关键点相矛盾 - 在编译时我不知道是否应该使用A.f
或B.f
。
答案 0 :(得分:6)
您必须使A.f
和B.f
具有相同的功能(在上面的示例中,它们只是具有相同名称的不同功能)。然后你可以在每个模块中重载一个方法,多个调度将完成它的工作。
实现此目的的方法是让其中一个模块从另一个模块导入函数f
(例如import A.f
中的B
),然后再使用新方法扩展它,或者添加第三个模块C
,其中包含f
和A
导入的B
函数(您可以使用永远不会创建的f(::Union()) = nothing
虚拟签名功能,无需添加任何实际方法)。我们直接从其他模块扩展功能,如
function A.f(x::Atype)
println("f called with A")
end
这将使Julia明白两个f
引用相同的概念,它们实际上是两个模块中的同一个对象。添加方法会修改通用函数对象,因此在使用f
的任何位置都可以看到此更改。