17.2 基础类型

不仅可以在 Scala 中使用 Java 的任何类型,

而且同时也可以享受到由 Scala 提供的一些原生类型。


Any类型

scala 的 Any 类型的所有超类型.

Any 类型可以作为任意类型对象的一个通用引用。

Any 是一个抽象类,定义了如下方 法:

!=()
##()
==()
asInstanceOf
equals()
hashCode()
isInstanceOf
toString()
getClass()

AnyValAnyRef

Any 类型的直接后裔是 AnyValAnyRef 类型。

AnyVal 是 Scala 中所有值类型(如 Int、Double 等)的基础类型,并映射到了 Java 中的原始类型,

AnyRef 是所有引用类型的基础类型。

尽管 AnyVal 没有什么额外的方法,但是 AnyRef 包含了 Java 的 Object 的方法,如 notify()、wait()、finalize()等。

Any 类型位于类型层次结构的最顶层,而最底层的类型是 Nothing


Nothin类型

在 Scala 中,Nothing 是一切类型的子类型。

我们很容易明白我们为何需要 Any 类型,但是 Nothing 类型在一开始看起来相当奇怪,特别是因为它代表了任何类型的子类型。

Nothing 类型在 Scala 的类型验证机制的支持上意义重大。

Scala 的类型推断尽可能地 确定表达式和方法的类型。如果推断出的类型太过宽泛,则不利于类型验证。

同时,我们确实也希望可以推断这样的表达式或函数的类型,例如: 在分支中, 其一个分支可以返回,如 Int 类型的结果, 而另一个分支抛出异常.

def someOp(number: Int) = {
    if (number < 10)
        number * 2
    else
        throw new RuntimeException("invalid argument")
}

在前面这种情况下,将该函数的返回类型推断为 Any 类型则太宽泛了,而且也没有什么用, 而将返回类型推断为 Int 则更为有用。

我们可以很容易地看出该算术表达式的计算结果类型为 Int

此外,也必须要推断抛出异常的分支的结果类型,在这种情况下,需要为其返回一个 Int 类型或者 Int 类型的子类型,以便使其和推断的返回类型兼容。

但是,throw 语句的结果类型不能被推断为 Int 类型而被任意处理, 因为在任何地方都可能会引发异常。 Nothing 类型这时候就派上用场了—--通过作为所有类型的子类型,它使类型推断过程得以顺利进行。

因为Nothing是所有类型的子类型,所以它可以替代任何东西。

Nothing 是抽象的,因此在运行时永远都不会得到一个真正的 Nothing 实例。它是一个纯粹的辅助类型,用于类型推断以及类型验证。


Option类型

Java 的空指针异常是所有程序员的梦魇. Java 之父曾经也说过 null的设计师他的一个错误.

在 Joshua Bloch 的 Effective Java[Blo08] 一书中有这样的合理建议: 返回空集合,而不是 null 引用。

如果遵循这个建议,我们就不必忍受 NullPointerException 了。

即使结果 集合为空,迭代也会变得很容易。在使用集合的时候,这是很好的建议,但是在使用其他返回类型时,我们也需要类似的内容。

例如,在执行模式匹配时,匹配的结果可能是对象、列表、元组等,也可能不存在。从两方面来说,悄无声息地返回一个 null 是有问题的。

  • 首先,可能没有结果值这个事实并没有被明确地(通过类型)表示出来。
  • 其次,没有办法强制要求函数的调用者来检查是不存在 还是 null

Scala 进一步指定了可能的不存在性。使用 Scala 的 Option[T],可以进行有意图的编程,并指定打算不返回结果。

Scala 以类型安全的方式实现了这一点,因此可以在编译时强制 进行检查。

Option有两个子类:SomeNone

当返回类型是Option的时候, 其实就是在告诉调用者: 哥们, 返回的值中有可能有null你要小心了.

object Test {
    def commentOnPractice(input: String) = { // 而不是返回 null
        if (input == "test")
            Some("good")
        else
            None
    }


    def main(args: Array[String]): Unit = {
        for (input <- Set("test", "hack")) {
            val comment = commentOnPractice(input)
            // 如果返回的是None, 则把参数返回
            val commentDisplay = comment.getOrElse("Found no comments")
            println(s"input: $input comment: $commentDisplay")
        }
    }
}

Either类型

当一个函数调用的结果可能存在也可能不存在时,Option 类型很有用。

有时候,你可能希望从一个函数中返回两种不同类型的值之一。 这个时候,ScalaEither 类型就派上用场了。

如果想要表明一个值可能不存在,就使用 `Option` 类型;但是,如果结果可能会在两个不同的值之间变化,就使用 `Either` 类型。

Either本身是个抽象类, 他有两个直接的实现子类: LeftRight

左值(Left)(通常被认为是错误)和右值(Right)(通常被认为是正确的或者符合预期的值)。

object Test {
    def compute(input: Int): Either[String, Double] = {
        if (input > 0)
            Right(math.sqrt(input))
        else
            Left("Error computing, invalid input")
    }

    def displayResult(result: Either[String, Double]): Unit = {
        result match {
            case Left(value) => println(s"result = $value")
            case Right(error) => println(s"error = $error")
        }
    }

    def main(args: Array[String]): Unit = {
        // 使用模式匹配来取出其中的值
        displayResult(compute(10))
        displayResult(compute(-10))
    }
}
Copyright © 尚硅谷大数据 2019 all right reserved,powered by Gitbook
该文件最后修订时间: 2019-04-12 09:03:53

results matching ""

    No results matching ""