【发布时间】:2012-11-24 09:08:39
【问题描述】:
Unit 和 Nothing 两种类型都表示一个不返回任何内容的函数。它们有什么区别?
【问题讨论】:
标签: scala
Unit 和 Nothing 两种类型都表示一个不返回任何内容的函数。它们有什么区别?
【问题讨论】:
标签: scala
Unit 是一个只有一个值的类型——参见Unit type。另一方面,Nothing 的值不可能 - 请参阅Bottom type。
不返回任何内容的函数必须具有返回类型Unit。如果是Nothing,则该函数无法返回结果。退出函数的唯一方法是通过异常。
Nothing 以不同的方式使用。它有两个特点:
Nothing 是所有其他类型的子类型(包括 Null)。什么时候有用?考虑None:
object None extends Option[Nothing]
因为Option 的类型参数是协变的,而Nothing 是所有事物的子类型,所以Option[Nothing] 是Option[A] 的每个类型A 的子类型。因此,我们可以为每个A 创建一个对象None,它是Option[A] 的子类型。这是合理的,因为Nothing 无法实例化,所以Option[Nothing] 将始终没有值。同样
object Nil extends List[Nothing]
Unit 对应于逻辑真,Nothing 对应于Curry-Howard isomorphism 下的逻辑假,我们将类型视为命题,将函数视为证明。
【讨论】:
Unit 表示 (a) 函数具有输入和输出等副作用,(b) 这些副作用是函数的主要目标。当然,即使函数的类型与Unit 不同,函数也会有副作用。
Nothing 是 Scala 中的一种特殊类型,因为 (a) 它没有值(单位只有一个值 - ()),所以你不能返回 Nothing 类型的值,并且 (b) 它是所有其他类型的子类型。这意味着如果某物的类型为Nothing,则可以使用它来代替任何其他类型(通过子类型化),但不会产生任何结果。这对于处理异常很有用 - throw 表达式的类型为 Nothing,因此它可以在程序中的任何地方使用。
简单来说,Nothing 表示程序出错或终止,没有任何返回,而Unit 表示有副作用,但执行正常结束,没有结果。
Programming in Scala 对此有很好的解释。
【讨论】:
在 Petr 的回复中添加一个方面:Nothing 在类型层次结构中起着重要作用。是底型。这意味着它是所有其他类型的子类型,就像 Any 的对立面,它是一切的超类型。你可以找到一个很好的解释here。
【讨论】:
单位
单位与Java的void相同。 Java 中的 void 是关键字,但 Kotlin 中的 Unit 是对象。
现在如果一个函数在 Kotlin 中返回 Unit,这意味着它没有返回任何有意义的东西,该函数只是执行一堆代码并返回 执行流程。
什么都没有
没有什么是完全不同的。您无法将它与 Java 中的任何内容联系起来。 在 java 中没有诸如 Nothing 之类的东西。
没有什么意味着执行结束。如果一个函数返回 Nothing,则意味着它没有返回任何内容。甚至不是执行流程。
没有什么比得上黑洞,任何进去的东西都出不来,甚至光也没有(光在这里是“执行流”)。在 Unit 的情况下,发出的光最少。
因此,如果一个函数返回 Nothing,则代码流到此结束,此后编写的任何内容都无法访问。
现在看下面的代码,
fun main() {
unitFun()
println("after unit")
nothingFun()
println("after nothing") //you get warning here saying "unreachable code"
}
fun nothingFun(): Nothing {
println("inside nothing")
throw Exception()
}
fun unitFun(): Unit {
println("inside unit")
}
输出将是
inside unit
after unit
inside nothing
Exception in thread "main" java.lang.Exception
注意:一写就收到警告
println("after nothing") UnReachable Code
而且你知道原因,因为 nothingFun 甚至没有发回执行流程。
这里要完成的另一件事是,任何返回 Nothing 的函数都必须抛出任何类型的异常。
原因:如果您编写一些通用语句(并且不抛出异常),那么该函数将匹配返回类型并且我们没有返回 Nothing 的任何内容,这意味着我们没有任何会吸收执行流程并且永远不会返回的东西。一切都返回一些东西,甚至 Unit 也是一些东西。
现在,可以说 Nothing 是一个类,因此我们可以将其作为对象并返回它本身。唔唔唔唔?一个很大的nohhhh?
没有一个类有一个构造函数,但它是私有的,所以你甚至不能为它创建一个对象。
最后一点
在幕后,Unit在反编译的字节码中被转换为void(small v),而Nothing被转换为Void(capital V)。
请看下面的代码,
var user = null //First
var user : User? =null //Second
这里,第二条语句显示,user 为 Nullable-User 类型。 第一条语句的用户是什么类型?
有什么猜测吗?
它是 Nullable-Nothing 类型。
尝试将第一条语句视为
var user : Nothing? = null
现在幕后发生了什么,
Void user = (Void)null; //First
User user = (User)null; //Second
【讨论】: