我刚读过:http://oldfashionedsoftware.com/2008/08/20/a-post-about-nothing/
据我了解,Null
是一个特征,其唯一的例子是null
。
当一个方法接受Null参数时,我们只能直接传递Null
引用或null
,而不能传递任何其他引用,即使它是null(nullString: String = null
for例子)。
我只是想知道在哪些情况下使用这个Null
特征会很有用。
还有一个我没有真正看到更多例子的Nothing特征。
我真的不明白使用Nothing和Unit作为返回类型之间的区别是什么,因为两者都没有返回任何结果,当我有一个执行日志记录的方法时,如何知道使用哪一个?
除了返回类型之外,您是否将Unit / Null / Nothing用作其他内容?
答案 0 :(得分:73)
如果方法永远不会返回(意味着它无法通过返回正常完成,它可能会抛出异常),则只使用Nothing。什么都没有被实例化,并且有利于类型系统(引用James Iry:"The reason Scala has a bottom type is tied to its ability to express variance in type parameters.")。从您链接的文章:
Nothing的另一个用途是作为从不的方法的返回类型 返回。如果你考虑它就有意义了。如果某个方法返回 type是Nothing,并且绝对没有Nothing的实例, 那么这种方法绝对不能回归。
您的日志记录方法将返回Unit。有一个值单位,所以它实际上可以返回。来自API docs:
Unit是scala.AnyVal的子类型。类型只有一个值 单位,(),它不由底层的任何对象表示 运行时系统。返回类型为Unit的方法类似于Java 声明为void的方法。
答案 1 :(得分:16)
您引用的文章可能会产生误导。 Null
类型用于与 Java虚拟机兼容,特别是Java。
我们必须考虑 Scala :
null
对访问的引用,例如,Java库和代码因此有必要为null
值定义一个类型,即Null
特征,并且null
作为唯一的实例。
在Null
类型中没有什么特别有用,除非您是类型系统或者您正在编译器上进行开发。特别是我看不出为方法定义Null
类型参数的任何明智理由,因为除了null
答案 2 :(得分:15)
你是否有单位/零/无的用法除了 返回类型?
Unit
可以像这样使用:
def execute(code: => Unit):Unit = {
// do something before
code
// do something after
}
这允许您传入要执行的任意代码块。
Null
可以用作任何可以为空的值的底部类型。一个例子是:
implicit def zeroNull[B >: Null] =
new Zero[B] { def apply = null }
Nothing
用于None
object None extends Option[Nothing]
这允许您为任何类型的None
分配Option
,因为Nothing
'扩展'所有内容。
val x:Option[String] = None
答案 3 :(得分:5)
我从未真正使用Null
类型,但您使用Unit
,您将使用void
。 Nothing
是一种特殊类型,因为内森已经提到过,Nothing
没有实例。 Nothing
是所谓的底部类型,这意味着它是任何其他类型的子类型。这个(以及逆变型参数)就是为什么你可以将任何值添加到Nil
- 这是一个List[Nothing]
- 然后列表将是这个元素类型。如果类型为None
,Option[Nothing]
也是Nothing
。每次尝试访问此类容器中的值都会引发异常,因为它是从{{1}}类型的方法返回的唯一有效方法。
答案 4 :(得分:5)
如果您使用Nothing
,则无需执行任何操作(包括打印控制台)
如果您执行某些操作,请使用输出类型Unit
object Run extends App {
//def sayHello(): Nothing = println("hello?")
def sayHello(): Unit = println("hello?")
sayHello()
}
...然后如何使用Nothing
?
trait Option[E]
case class Some[E](value: E) extends Option[E]
case object None extends Option[Nothing]
答案 5 :(得分:3)
通常隐式使用。在下面的代码中,
val b: Boolean =
if (1 > 2) false
else throw new RuntimeException("error")
else 子句的类型为 Nothing ,它是Boolean的子类(以及任何其他AnyVal)。因此,整个赋值对编译器有效,尽管 else 子句并不真正返回任何内容。
答案 6 :(得分:1)
以下是来自Nothing
的{{1}}的示例:
scala.predef
如果您不熟悉(并且搜索引擎无法对其进行搜索), def ??? : Nothing = throw new NotImplementedError
是Scala的占位符函数,用于尚未实施的任何内容。就像Kotlin的???
。
创建模拟对象时可以使用相同的技巧:使用自定义TODO
方法覆盖未使用的方法。不使用notUsed
的好处是你不会为你从未打算实现的事情获得编译警告。
答案 7 :(得分:0)
就类别理论而言,没有是初始对象,而 Unit 是终端对象。>
https://en.wikipedia.org/wiki/Initial_and_terminal_objects
初始对象也称为共同终端或通用,而终端对象也称为最终。
如果一个对象既是初始也是终端,则称为零对象或空对象。