我有一个类型AbstractT
,并且我想要为每个子类型定义一个构造函数T(x::Tuple)
,但我找不到一种通用的方法来执行它,因为Julia中的所有内容都使用了dispatch ,但我不能在构造函数上调度,因为构造函数的名称与类型匹配,因此每个构造函数是一个不同的函数。即如果有
construct{T<:AbstractT}(::Type{T},x::Tuple) = # Define all the constructors
我在内部这样做,但是它与其他将直接调用T(x)和错误的包很好地协同工作。朱莉娅是否以某种方式使用发动机下的调度?
答案 0 :(得分:7)
它看起来有点滑稽,但你实际上可以发送功能本身!对于构造函数,函数是有问题的类型:
julia> abstract AbstractT
immutable ConcreteT{T} <: AbstractT; end
julia> (::Type{ConcreteT{Int}})() = 1
(::Type{ConcreteT{Float64}})() = 2
julia> ConcreteT{Int}()
1
julia> ConcreteT{Float64}()
2
你甚至可以使用类型参数......它们位于函数名和参数列表之间的正常位置,所以它看起来有点倒退,但它的工作正常:
julia> (::Type{ConcreteT{T}}){T<:Number}() = 3
(::Type{ConcreteT{T}}){T<:AbstractArray}() = 4
julia> ConcreteT{Float32}()
3
julia> ConcreteT{UnitRange{Int}}()
4
您甚至可以使用抽象类型执行此操作,但请注意:
julia> (::Type{T}){T<:AbstractT}() = 5
julia> ConcreteT{String}()
ConcreteT{String}()
julia> AbstractT()
5
为什么抽象构造函数不能用于ConcreteT{String}
?回想一下,Julia为你创建了构造函数......因为这只是调度,所以这些构造函数更具体并且优先:
julia> methods(ConcreteT{String})
# 3 methods for generic function "(::Type)":
(::Type{ConcreteT{T}}){T}() at REPL[1]:2
(::Type{T}){T<:AbstractT}() at REPL[8]:1
(::Type{T}){T}(arg) at sysimg.jl:53
因此在使用此功能时需要小心;只有当它不与你的叶子构造器冲突时它才会起作用:
julia> (::Type{T}){T<:AbstractT}(x) = x
julia> ConcreteT{String}(6)
6
julia> ConcreteT{Int}(7)
7