上QQ阅读APP看书,第一时间看更新
6.6 类型联合
有时候,无论是类型的别称还是抽象都难以满足程序设计的需求。例如某个函数的参数,我们希望是Int64或Float32型,但不能是任何其他的类型。这样的要求,采用前文介绍的方式是难以实现的。
Julia中提供了一种可以将多种类型进行“或组合”的方式,即类型联合(Type Unions),定义的基本语法为:
Union{T1, T2, 厎
其中,Union会将大括号内以逗号分隔的多个类型进行组合,变成单一的类型。
例如,我们可以声明一个内部类型元素为Int64与Float32的类型联合,代码如下:
julia> IntOrFloat64 = Union{Int64,Float64} Union{Float64, Int64} julia> typeof(IntOrFloat64) Union
此时对其进行相关类型的继承关系断言,便会发现除了Int64与Float64外,其他的类型都不是其子类型:
julia> Int64 <: IntOrFloat64 true julia> Float64 <: IntOrFloat64 true julia> FooA <: IntOrFloat64 # FooA是前文曾声明过的复合类型 false julia> Real <: IntOrFloat64 false
如此一来,便实现了对多个类型进行组合限定的目的。
在类型联合的基础上,我们便可用其限定具体值的类型,只有满足类型断言的对象才能够获得有效操作。例如:
julia> 1::IntOrFloat64 1 julia> 2.3::IntOrFloat64 2.3 julia> a = Int32(1) 1 julia> a::IntOrFloat64 ERROR: TypeError: typeassert: expected Union{Float64, Int64}, got Int32
其中,变量a因为类型是Int32,既不是Int64也不是Float64,所以会上报Type Error异常。
Union在元素类型上并没有过多限制,不仅适用于基本的类型,也适用于其他更多的类型。例如:
julia> MockType = Union{FooA, FooB, Integer};
其中,MockType将复合类型与普通的抽象类型进行了联合,构造出了新的类型。将其与其他各种类型对比断言,便会发现其确实对元素中的类型有了准确的限定约束,代码如下所示:
julia> FooA <: MockType true julia> FooB <: MockType true julia> MockType >: Signed # 其中的Integer是Signed的父类型 true julia> MockType >: AbstractFloat false julia> MockType >: Bar # Bar是前文曾声明过的复合类型 false
另外一个事实是,虽然类型联合的类型是Union而非是DataType,但Union的类型却是DataType,即:
julia> typeof(Union) DataType
所以类型联合也是DataType的实例对象,同样也是类型系统的一部分。
但是,Union的直接父类型并非是Any类型,而是:
julia> supertype(Union) Type{T}
其中,Type{T}是一种特殊的参数化类型,将会在接下来的内容中进行介绍。