Dive Into Kotlin(四):为何 Kotlin 的根类型是「Any?」

本文由 Prefert 发表在 ScalaCool 团队博客。编程

咱们在Dive Into Kotlin(二):Kotlin 类型结构设计中已经对Kotlin的类型系统进行过大体的介绍。bash

文中提到过: Any 类型是 Kotlin 中 全部非空类型(ex: String, Int) 的根类型。编程语言

当咱们须要和 Java 互操做的时候,Kotlin 把 Java 方法参数和返回类型中用到的 Object 类型看做 Any(更确切地说是当作「平台类型」)。当 Kotlin 函数中使用 Any 时,它会被编译成 Java 字节码中的 Object函数

什么是平台类型?ui

平台类型本质上就是 Kotlin 不知道可空性信息的类型—全部 Java 引用类型在 Kotlin 中都表现为平台类型。当在 Kotlin 中处理平台类型的值的时候,它既能够被当作可空类型来处理,也能够被当作非空类型来操做。spa

平台类型的引入是 Kotlin 兼容 Java 时的一种权衡设计。试想下,若是全部来自 Java 的值都被当作非空,那么就容易写出比较危险的代码。反之,若是 Java 值都强制当作可空,则会致使大量的 null 检查。综合考量,平台类型是一种折中的设计方案。scala

在 Java 中,Object 类型位于其类型系统的顶级。若是说 Kotlin 与 Java 是100%兼容的,那咱们是否能够说 Any 也是Kotlin的全部类型的顶级类型呢?在上一篇文章中,这个问题一样困扰了我,官方也并无作出一个明确的说明。可是咱们能够注意到的是, Kotlin 中引入了「可空类型」这个概念,这极可能会对系统层级结构产生影响。设计

在探索根类型以前,先让咱们理清两个概念:继承(Inheriting)和 子类型化(Subtyping)。code

继承和子类型化的区别

这是一个看似容易实则不简单的问题:到底什么才是子类型化( Subtyping )?咱们曾在Subtyping vs Typeclasses(一)这篇博客讨论过这个问题。若是你只有 Java 这门编程语言的开发经验,很容易陷入一个误区——继承关系决定父子类型关系。由于在 Java 中, 类与类型大部分状况下都是「等价」的(在 Java 泛型出现前)。cdn

事实上,「继承」和「子类型化」是两个彻底不一样的概念。

  • 子类型化的核心是一种类型的替代关系(咱们也能够称之为子类型多态),一般可表示为:

    S <: T
    复制代码

    以上 ST 的子类,这意味着在须要 T 类型值的地方,S 类型的值一样适用,如在 Kotlin 中 IntNumber 的子类:

    fun printNum(num: Number) {
      println(num)
    }
    
    >>> val n: Int = 1
    >>> printNum(n)
    
    >>> 1
    >>> printNum("I am a String")
    error: type mismatch: inferred type is String but Number was expected
    复制代码
  • 相对而言,继承强调的是一种「实现上的复用」,而子类型化是一种类型语义的关系,与实现不要紧。在 Java 中,咱们彷佛也能够经过类继承来实现上述关系:

    class S extends class T 复制代码

    因为在声明父子类型关系的同时,也声明了继承的关系,因此一般会形成了某种程度上的混淆,可是这并不能说明这两个概念就是等价的。

虽然 AnyAny? 看起来没有继承关系,然而当咱们在须要用 Any? 类型值的地方,显然能够传入一个类型为 Any 的值,这在编译上不会产生问题。反之却行不通,好比:一个参数类型为 Any 的函数,咱们传入符合 Any? 类型的 null 值,就会出现以下的错误:

error: null can not be a value of a non-null type Any
复制代码

以上,咱们也能够初步得出结论:Any的值能在全部状况下代替 Any? 的值,这符合「子类型化」的概念。

所以,咱们能够很大胆地说:在Kotlin的类型系统中,Any?Any 的父类型,并且是全部类型的根类型,虽然当前的 Kotlin 官网文档没有介绍过这一点。

Any? 与 Any??

一个你可能会挑战的问题是,若是 Any?Any 的父类型,那么 Any?? 是否又是 Any? 的父类型, 若是成立,那么是否意味着就没有所谓的「全部类型的根类型」了?

其实,Kotlin 中的可空类型能够看作所谓的 Union Type,在程序中一般用 A | B 表示,近似于数学中的并集。若是用类型的并集来表示 Any? ,可写为 Any ∪ Null。相应的 Any?? 就表示为 Any ∪ Null ∪ Null,这等价于 Any ∪ Null, 即 Any?? 等价于 Any? 。所以,说 Any? 是全部类型的根类型是没有问题的。

相关文章
相关标签/搜索