对我来说,他们似乎是一样的。由于Type
属于DataType
类型,反之亦然,它们如何不等同?我应该何时使用其中一种?
> isa(DataType, Type)
true
> typeof(Type)
DataType
> isa(Type, DataType)
true
> typeof(DataType)
DataType
答案 0 :(得分:7)
Type
和DataType
本身就是两种类型。正如您所发现的,大多数类型的类型都是DataType
。在这种情况下,DataType
是摘要Type
:
julia> supertype(DataType)
Type{T}
julia> supertype(Type)
Any
julia> DataType <: Type
true
这意味着isa
DataType
也将是Type
的任何内容 - Julia 中的这么多类型都是 isa
。还有Type
的其他子类型,包括Union
和TypeConstructor
s。这意味着julia中的所有类型都属于Type
类型,但即使像Vector
这样的简单内容也不属于DataType
类型。
Type
很特别。如上所示,它是参数化的。这允许您精确指定相关特定类型的类型。因此,虽然朱莉娅isa
Type
中的每一种类型都只有Int
isa
Type{Int}
:
julia> isa(Int, Type{Int})
true
julia> isa(Float64, Type{Int})
false
julia> isa(Float64, Type)
true
此功能对于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"
值得注意的是Type{Number}
仅 Number
的类型,而不是Int
的类型,即使是Int <: 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"
将有问题的特定类型捕获为函数参数的功能非常强大且经常使用。请注意,我甚至不需要指定参数名称 - 在这种情况下唯一重要的是Type{}
中的参数。
这对于什么是一个非常简短的答案来说是一个很长的解释:你通常不想使用DataType
,因为它不会涵盖朱莉娅的所有类型。相反,您应该使用Type
来描述任何或所有类型的类型。如果要特别描述Type{T}
的类型,请使用T
。