Julia语言程序设计
上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}是一种特殊的参数化类型,将会在接下来的内容中进行介绍。