对我来说,他们似乎是一样的.由于Type是类型DataType,反之亦然,它们如何不等同?我什么时候应该使用一个?
> isa(DataType, Type)
true
> typeof(Type)
DataType
> isa(Type, DataType)
true
> typeof(DataType)
DataType
Run Code Online (Sandbox Code Playgroud)
Type和DataType本身这两种类型.正如您所发现的那样,大多数类型的类型DataType.在这种情况下,DataType是抽象的子类型Type:
julia> supertype(DataType)
Type{T}
julia> supertype(Type)
Any
julia> DataType <: Type
true
Run Code Online (Sandbox Code Playgroud)
这意味着任何也isa DataType将成为Type朱莉娅这么多类型的 isa东西都是.还有其他的亚型Type,包括Unions和TypeConstructors.这意味着julia 中的所有类型都是类型Type,但即使是简单的事情Vector也不会是类型DataType.
Type很特别.如上所示,它是参数化的.这允许您精确指定相关特定类型的类型.所以尽管Julia中的每一种类型都isa Type只有Int isa Type{Int}:
julia> isa(Int, Type{Int})
true
julia> isa(Float64, Type{Int})
false
julia> isa(Float64, Type)
true
Run Code Online (Sandbox Code Playgroud)
这种能力是特殊和独特的Type,它对于允许在特定类型上指定调度至关重要.例如,许多函数允许您指定类型作为其第一个参数.
f(x::Type{String}) = "string method, got $x"
f(x::Type{Number}) = "number method, got $x"
julia> f(String)
"string method, got String"
julia> f(Number)
"number method, got Number"
Run Code Online (Sandbox Code Playgroud)
值得注意的Type{Number}是,即使只是类型Number,而不是类型!这是参数不变性.要允许特定抽象类型的所有子类型,可以使用函数参数:IntInt <: Number
julia> f(Int)
ERROR: MethodError: no method matching f(::Type{Int64})
julia> f{T<:Integer}(::Type{T}) = "integer method, got $T"
f (generic function with 3 methods)
julia> f(Int)
"integer method, got Int64"
Run Code Online (Sandbox Code Playgroud)
捕获作为函数参数的特定类型的能力是强大且经常使用的.请注意,我甚至不需要指定参数名称 - 在这种情况下唯一重要的是其中的参数Type{}.
这对于什么是一个非常简短的答案来说是一个很长的解释:你通常不想使用DataType,因为它不会涵盖朱莉娅的所有类型.相反,您应该Type用来描述任何或所有类型的类型.使用Type{T}时,你想描述的类型,T尤其如此.