抽象类型的子类型的通用构造函数

时间:2016-10-20 16:47:52

标签: types julia

我有一个类型AbstractT,并且我想要为每个子类型定义一个构造函数T(x::Tuple),但我找不到一种通用的方法来执行它,因为Julia中的所有内容都使用了dispatch ,但我不能在构造函数上调度,因为构造函数的名称与类型匹配,因此每个构造函数是一个不同的函数。即如果有

它会起作用
construct{T<:AbstractT}(::Type{T},x::Tuple) = # Define all the constructors

我在内部这样做,但是它与其他将直接调用T(x)和错误的包很好地协同工作。朱莉娅是否以某种方式使用发动机下的调度?

1 个答案:

答案 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