Scala中的Unit和Nothing有什么区别?

3
我很乐意为您澄清一些关于“Unit”和“Nothing”的细节问题。以下是一个示例:
例如:
def unit(companyId: Int): Unit = {}

def Nothing(companyId: Int): scala.Nothing = {}

根据文档,Scala中的Unit与Java中的void非常相似。但是。
test("test Unit and Nothing") {
  println(unit(1))
}
  • Unit返回-()

  • Nothing不返回任何内容。

为什么Scala有一个溢出类型的Unit,它返回Nothing? 为什么Scala不能使用Nothing代替Unit


1
可能是Scala中Null / Nothing / Unit的用法的重复。 - Tzach Zohar
3
“overflow”的意思是“溢出”。 - Chris Martin
欢迎来到StackOverflow!为了感谢您的同行抽出时间回答您的问题,请接受他们的答案:http://stackoverflow.com/help/someone-answers - manub
1个回答

13

Unit 的基数为1。 Nothing 的基数为0。

你的第二个例子

def Nothing(companyId: Int): scala.Nothing = {}

无法编译。返回Nothing是不可能的,因为Nothing没有实例。因此,返回Nothing的函数无法正常返回,只能抛出异常。

def Nothing(companyId: Int): scala.Nothing = { throw new Exception(); }

Java中的VoidUnit相似,因为Void也具有基数1;它唯一的实例是null。在Java中不存在基数为0的类型(也不可能定义这样的类型),因此Java没有可与Nothing相比较的类型。


考虑在集合中使用它们时会发生什么。例如,List[Unit]可以包含任意数量的Unit值:

List()           : List[Unit]
List((), (), ()) : List[Unit]

相比之下,List[Nothing] 是必然为空的,因为你无法往其中添加任何元素。

List()           : List[Nothing]

关于Nothing的另一个重要之处在于它是每个类型的子类型。这很有道理,因为它没有任何元素;因此关于Nothing实例的每个命题(命题与类型密切相关)都是真的。为了说明为什么这很有用,再次考虑列表:

List.empty[Nothing] : List[String]

我们将一个 List[Nothing] 归属于类型 List[String],这是因为 List 的类型参数是协变的,而 NothingString 的子类型。需要注意的是,如果是 List[Unit],我们不能这样做,因为 Unit 不是 String 的子类型。


感谢您的详细解释。我熟悉List [Nothing],Nil,Liskov替换等等。但我的问题不同。为什么如果函数不返回数据,需要使用Unit,并实际返回()而不是Nothing。 - user5607337
@scala 或许这篇博客文章 http://james-iry.blogspot.ch/2009/08/getting-to-bottom-of-nothing-at-all.html?m=1 可以帮助您获得一些额外的直觉。 - godfatherofpolka

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接