Scala 中 Null/Nothing/Unit 的用法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16173477/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 05:12:50  来源:igfitidea点击:

Usages of Null / Nothing / Unit in Scala

scala

提问by Sebastien Lorber

I've just read: http://oldfashionedsoftware.com/2008/08/20/a-post-about-nothing/

我刚刚读过:http: //oldfashionedsoftware.com/2008/08/20/a-post-about-nothing/

As far as I understand, Nullis a trait and its only instance is null.

据我了解,Null是一个特征,它的唯一实例是null.

When a method takes a Null argument, then we can only pass it a Nullreference or nulldirectly, but not any other reference, even if it is null (nullString: String = nullfor example).

当一个方法接受一个 Null 参数时,我们只能向它传递一个Null引用或null直接传递,而不能传递任何其他引用,即使它是 null(nullString: String = null例如)。

I just wonder in which cases using this Nulltrait could be useful. There is also the Nothing trait for which I don't really see any more examples.

我只是想知道在哪些情况下使用这个Null特性会很有用。还有我没有真正看到更多例子的Nothing特征。



I don't really understand either what is the difference between using Nothing and Unit as a return type, since both doesn't return any result, how to know which one to use when I have a method that performs logging for example?

我真的不明白使用 Nothing 和 Unit 作为返回类型有什么区别,因为两者都不返回任何结果,例如,当我有一个执行日志记录的方法时,如何知道使用哪个?



Do you have usages of Unit / Null / Nothing as something else than a return type?

除了返回类型之外,您是否将 Unit / Null / Nothing 用作其他用途?

采纳答案by Nathan Hughes

You only use Nothing if the method never returns (meaning it cannot complete normally by returning, it could throw an exception). Nothing is never instantiated and is there for the benefit of the type system (to quote James Iry: "The reason Scala has a bottom type is tied to its ability to express variance in type parameters."). From the article you linked to:

如果该方法从不返回,则仅使用 Nothing(意味着它无法通过返回正常完成,它可能会引发异常)。没有什么是永远不会被实例化的,并且是为了类型系统的利益而存在的(引用 James Iry 的话说:“Scala 具有底部类型的原因与其在类型参数中表达差异的能力有关。”)。从您链接到的文章:

One other use of Nothing is as a return type for methods that never return. It makes sense if you think about it. If a method's return type is Nothing, and there exists absolutely no instance of Nothing, then such a method must never return.

Nothing 的另一种用途是作为永不返回的方法的返回类型。如果你考虑一下,这是有道理的。如果一个方法的返回类型是Nothing,并且绝对不存在Nothing 的实例,那么这样的方法绝不能返回。

Your logging method would return Unit. There is a value Unit so it can actually be returned. From the API docs:

您的日志记录方法将返回 Unit。有一个值 Unit,所以它实际上可以返回。来自API 文档

Unit is a subtype of scala.AnyVal. There is only one value of type Unit, (), and it is not represented by any object in the underlying runtime system. A method with return type Unit is analogous to a Java method which is declared void.

Unit 是 scala.AnyVal 的一个子类型。Unit类型的值只有一个,(),在底层运行时系统中不由任何对象表示。返回类型为 Unit 的方法类似于声明为 void 的 Java 方法。

回答by pagoda_5b

The article you quote can be misleading. The Nulltype is there for compatibility with the Java virtual machine, and Java in particular.

您引用的文章可能具有误导性。该Null类型是为了与Java 虚拟机,特别是Java兼容。

We must consider that Scala:

我们必须考虑Scala

  • is completely object oriented: every value is an object
  • is strongly typed: every value must have a type
  • needs to handle nullreferences to access, for example, Java libraries and code
  • 完全面向对象:每个值都是一个对象
  • 是强类型的:每个值都必须有一个类型
  • 需要处理null对访问的引用,例如 Java 库和代码

thus it becomes necessary to define a type for the nullvalue, which is the Nulltrait, and has nullas its only instance.

因此有必要为null值定义一个类型,它是Null特征,并且具有null作为它的唯一实例。

There is nothing especially useful in the Nulltype unless you're the type-system or you're developing on the compiler. In particular I can't see any sensible reason to define a Nulltype parameter for a method, since you can't pass anything but null

Null除非您是类型系统或您在编译器上进行开发,否则类型中没有什么特别有用的东西。特别是我看不出有任何合理的理由来定义Null一个方法的类型参数,因为除了null

回答by EECOLOR

Do you have usages of Unit / Null / Nothing as something else than a return type?

除了返回类型之外,您是否将 Unit / Null / Nothing 用作其他用途?



Unitcan be used like this:

Unit可以这样使用:

def execute(code: => Unit):Unit = {
  // do something before
  code
  // do something after
}

This allows you to pass in an arbitrary block of code to be executed.

这允许您传入要执行的任意代码块。



Nullmight be used as a bottom type for any value that is nullable. An example is this:

Null可以用作任何可为空的值的底部类型。一个例子是这样的:

implicit def zeroNull[B >: Null] =
    new Zero[B] { def apply = null }


Nothingis used in the definition of None

Nothing用于定义 None

object None extends Option[Nothing]

This allows you to assign a Noneto any type of Optionbecause Nothing'extends' everything.

这允许您将 a 分配None给任何类型,Option因为Nothing“扩展”了所有内容。

val x:Option[String] = None

回答by Curycu

if you use Nothing, there is no things to do (include print console) if you do something, use output type Unit

如果您使用Nothing,则无事可做(包括打印控制台)如果您执行某事,请使用输出类型Unit

object Run extends App {
  //def sayHello(): Nothing = println("hello?")
  def sayHello(): Unit = println("hello?")
  sayHello()
}

... then how to use Nothing?

……那怎么用Nothing呢?

trait Option[E]
case class Some[E](value: E) extends Option[E]
case object None extends Option[Nothing]

回答by drexin

I've never actually used the Nulltype, but you use Unit, where you would on java use void. Nothingis a special type, because as Nathan already mentioned, there can be no instance of Nothing. Nothingis a so called bottom-type, which means, that it is a sub-type of any other type. This (and the contravariant type parameter) is why you can prepend any value to Nil- which is a List[Nothing]- and the list will then be of this elements type. Nonealso if of type Option[Nothing]. Every attempt to access the values inside such a container will throw an exception, because that it the only valid way to return from a method of type Nothing.

我从来没有真正使用过这个Null类型,但是你使用了Unit,你会在 java 上使用voidNothing是一种特殊类型,因为正如 Nathan 已经提到的,不能有Nothing. Nothing是所谓的底部类型,这意味着它是任何其他类型的子类型。这(以及逆变类型参数)就是为什么您可以将任何值添加到Nil- 即 a List[Nothing]- 然后列表将属于该元素类型。None也是如果类型Option[Nothing]。每次尝试访问此类容器中的值都会引发异常,因为这是从 类型方法返回的唯一有效方法Nothing

回答by Fang Zhang

Nothingis often used implicitly. In the code below, val b: Boolean =if (1 > 2) falseelse throw new RuntimeException("error")the elseclause is of type Nothing, which is a subclass of Boolean (as well as any other AnyVal). Thus, the whole assignment is valid to the compiler, although the elseclause does not really return anything.

没有经常隐式使用。在下面的代码, val b: Boolean =if (1 > 2) falseelse throw new RuntimeException("error")所述其他子句是类型没有什么,这是布尔的子类(以及任何其他AnyVal)。因此,整个赋值对编译器是有效的,尽管else子句并没有真正返回任何东西。

回答by David Leppik

Here's an example of Nothingfrom scala.predef:

以下是Nothingfrom的示例scala.predef

  def ??? : Nothing = throw new NotImplementedError

In case you're unfamiliar (and search engines can't search on it) ???is Scala's placeholder function for anything that hasn't been implemented yet. Just like Kotlin's TODO.

如果您不熟悉(并且搜索引擎无法对其进行搜索)???,Scala 的占位符功能可用于尚未实现的任何内容。就像 Kotlin 的TODO.

You can use the same trick when creating mock objects: override unused methods with a custom notUsedmethod. The advantage of not using ???is that you won't get compile warnings for things you never intend to implement.

您可以在创建模拟对象时使用相同的技巧:使用自定义notUsed方法覆盖未使用的方法。不使用的好处???是你不会因为你从未打算实现的东西得到编译警告。

回答by Joe

In terms of category theory Nothingis an initial objectand Unitis a terminal object.

就范畴论而言,Nothing初始对象Unit终结对象

https://en.wikipedia.org/wiki/Initial_and_terminal_objects

https://en.wikipedia.org/wiki/Initial_and_terminal_objects

Initial objectsare also called coterminalor universal, and terminal objectsare also called final.

初始对象也称为共同终结通用对象终结对象也称为终结对象

If an object is both initialand terminal, it is called a zero objector nullobject.

如果一个对象是既初始终端,它被称为零对象对象。