I have a type AbstractT
and for each subtype I want to define a constructor T(x::Tuple)
, but I can't find a generic way to do it because everything in Julia like this uses dispatch, but I cannot dispatch on the constructor since the name of the constructor matches the type and so each constructor is a different function. i.e. it would work if there was a
construct{T<:AbstractT}(::Type{T},x::Tuple) = # Define all the constructors
and I do that internally, but then it doesn't work nicely with other packages which will call T(x) directly and error. Is Julia using dispatch under the hood in some way that I could tap into?
It's a little funny-looking, but you actually can dispatch on the type of the function itself! In the case of a constructor, the function is the type in question:
julia> abstract type AbstractT end
julia> struct ConcreteT{T} <: AbstractT; end
julia> (::Type{ConcreteT{Int}})() = 1
julia> (::Type{ConcreteT{Float64}})() = 2
julia> ConcreteT{Int}()
1
julia> ConcreteT{Float64}()
2
You can even use type parameters… they go in the normal place after the function name and the argument list:
julia> (::Type{ConcreteT{T}})() where {T<:Number} = 3
julia> (::Type{ConcreteT{T}})() where {T<:AbstractArray} = 4
julia> ConcreteT{Float32}()
3
julia> ConcreteT{UnitRange{Int}}()
4
You can even do this with your abstract types, but watch out:
julia> (::Type{T})() where {T<:AbstractT} = 5
julia> ConcreteT{String}()
ConcreteT{String}()
julia> AbstractT()
5
Why didn't the abstract constructor work for ConcreteT{String}
? Recall that Julia creates constructors for you… and since this is just dispatch, those constructors are more specific and take precedence:
julia> methods(ConcreteT{String})
# 2 methods for type constructor:
[1] (::Type{ConcreteT{T}})() where T in Main at REPL[2]:1
[2] (::Type{T})() where T<:AbstractT in Main at REPL[12]:1
So you need to be careful when using this capability; it'll only work if it doesn't clash with your leaf constructors:
julia> (::Type{T})(x) where {T<:AbstractT} = x
julia> ConcreteT{String}(6)
6
julia> ConcreteT{Int}(7)
7
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With