4.2 类型与值

我们在前面提到了子类型(subtype)这个概念。与之相对的概念是超类型(supertype)。比如说,Integer类型是Signed类型的直接超类型,并且还是Int64类型的间接超类型。如果用操作符<:来表示的话,那就是:Int64 <: Signed <: Integer

实际上,Julia 中预定义的所有类型共同构成了一幅具有层次的类型图。这幅类型图中的类型之间都是有关系的。更具体地说,它们要么存在着直接或间接的继承关系,要么有着共同的超类型。

每一个 Julia 程序都会使用甚至定义一些类型。正因为如此,我们的程序才与 Julia 的类型系统关联在了一起。可以说,我们在编写程序时总会使用到 Julia 的类型图,并且有时候(即在自定义类型时)还会对这幅图进行扩展。我们定义的所有类型都会有一个超类型,即使我们没有显式地指定它。如此一来,我们的类型就与 Julia 原有的类型图联系在一起了。

我们之前说过,Julia 代码中的任何值都是有类型的。或者说,Julia 程序中的每一个值都分别是其所属类型的一个实例。不仅如此,每一个值也都分别是其所属类型的所有超类型的一个实例。例如:

  1. julia> 10::Int64, 10::Signed, 10::Integer
  2. (10, 10, 10)
  3. julia>

可以看到,上例中的 3 个类型断言都成功了。也就是说,10这个值既是Int64类型的一个实例,也是Signed类型和Integer类型的一个实例。

此外,Julia 代码中所有的值都是对象(object)。但与那些传统的支持面向对象编程的语言不同,Julia 中的对象(或者说这些对象所属的类型)并不会包含或关联任何方法。恰恰相反,一个函数会用它的衍生方法去尽量适应被操作的对象。这正是由 Julia 的多重分派机制来控制的。

再次强调,Julia 中只有值才有类型,而变量本身是没有类型的。一个变量代表的只是一个标识符与某个值之间的绑定关系。