这一节我们要讲Julia的一个重要特性——多重派发(multiple dispatch)。
为了更好理解Julia中的多重派发,可以来看看Julia+
运算符。通过对+
调用methods()
函数,可以看出Juila中已经有多少关于+
运算符的定义。
methods(+)
184 methods for generic function +:
...
- +(x::Dates.CompoundPeriod, y::Dates.CompoundPeriod) in Dates at /opt/apps/julia/share/julia/stdlib/v1.5/Dates/src/periods.jl:347
- +(x::Dates.CompoundPeriod, y::Dates.Period) in Dates at /opt/apps/julia/share/julia/stdlib/v1.5/Dates/src/periods.jl:345
- +(J::LinearAlgebra.UniformScaling, F::LinearAlgebra.Hessenberg) in LinearAlgebra at /opt/apps/julia/share/julia/stdlib/v1.5/LinearAlgebra/src/hessenberg.jl:560
- +(a, b, c, xs...) in Base at operators.jl:538
可以使用which
宏查看我们在使用+
运算符时到底使用了哪个方法。
@which 3 + 3
@which 3 + 3.0
+(x::Number, y::Number) in Base at promotion.jl:311
@which 3.0 + 3.0
+(x::Float64, y::Float64) in Base at float.jl:401
此外,我们也可以为+
扩展新的方法。
首先需要从Base库导入+
import Base: +
比如我们想用+
串联字符串。+
原本是没有这个功能的。
"hello " + "world!"
MethodError: no method matching +(::String, ::String)
Closest candidates are:
+(::Any, ::Any, !Matched::Any, !Matched::Any…) at operators.jl:538Stacktrace:
[1] top-level scope at In[10]:1
[2] include_string(::Function, ::Module, ::String, ::String) at ./loading.jl:1091
[3] execute_code(::String, ::String) at /home/lupeng/.julia/packages/IJulia/a1SNk/src/execute_request.jl:27
[4] execute_request(::ZMQ.Socket, ::IJulia.Msg) at /home/lupeng/.julia/packages/IJulia/a1SNk/src/execute_request.jl:86
[5] #invokelatest#1 at ./essentials.jl:710 [inlined]
[6] invokelatest at ./essentials.jl:709 [inlined]
[7] eventloop(::ZMQ.Socket) at /home/lupeng/.julia/packages/IJulia/a1SNk/src/eventloop.jl:8
[8] (::IJulia.var"#15#18")() at ./task.jl:356
@which "hello " + "world!"
no unique matching method found for the specified argument types
Stacktrace:
[1] error(::String) at ./error.jl:33
[2] which(::Any, ::Any) at ./reflection.jl:1158
[3] top-level scope at In[11]:1
[4] include_string(::Function, ::Module, ::String, ::String) at ./loading.jl:1091
[5] execute_code(::String, ::String) at /home/lupeng/.julia/packages/IJulia/a1SNk/src/execute_request.jl:27
[6] execute_request(::ZMQ.Socket, ::IJulia.Msg) at /home/lupeng/.julia/packages/IJulia/a1SNk/src/execute_request.jl:86
[7] #invokelatest#1 at ./essentials.jl:710 [inlined]
[8] invokelatest at ./essentials.jl:709 [inlined]
[9] eventloop(::ZMQ.Socket) at /home/lupeng/.julia/packages/IJulia/a1SNk/src/eventloop.jl:8
[10] (::IJulia.var"#15#18")() at ./task.jl:356
现在我们来为+
添加串联字符串的功能。
+(x::String, y::String) = string(x, y)
- (generic function with 185 methods)
"hello " + "world!"
“hello world!”
@which "hello " + "world!"
+(x::String, y::String) in Main at In[13]:1
再看一个例子
foo(x, y) = println("duck-typed foo!")
foo(x::Int, y::Float64) = println("foo with an integer and a float!")
foo(x::Float64, y::Float64) = println("foo with two floats!")
foo(x::Int, y::Int) = println("foo with two integers!")
foo (generic function with 4 methods)
foo(1, 1)
foo with two integers!
foo(1., 1.)
foo with two floats!
foo(1, 1.0)
foo with an integer and a float!
foo(true, false)
duck-typed foo!