在 Scala 中使用构造函数扩展 class 的案例对象

Case object extending class with constructor in Scala

我是 Scala 的初学者,正在尝试了解有关抽象数据类型的更多信息。我定义了以下定义来复制选项类型:

sealed abstract class Maybe[+A](x:A)
case object Nothing extends Maybe[Nothing](Nothing)
case class Just[A](x:A) extends Maybe[A](x)

但是我遇到了如下错误。

found   : Nothing.type
required: Nothing
    case object Nothing extends Maybe[Nothing](Nothing)

如何传递 Nothing 而不是 Nothing.type

我参考了以下问题以获取提示: How to extend an object in Scala with an abstract class with constructor?,但没有帮助。

也许更像这样。你的 Nothing 不应该有值,只有类型。此外,人们通常使用特征而不是抽象 类.

sealed trait Maybe[+A]
case object None extends Maybe[Nothing]
case class Just[A](x:A) extends Maybe[A]

您可能不应该创建自己的 Nothing,那会造成混淆,您会混淆自己和编译器,不知道您指的是您自己的 Nothing 还是类型层次结构底部的 Nothing。

正如 Stephen 所提到的,正确的做法是不要有 trait 而不是抽象 class,但是,我认为解释当前方法失败的原因以及如何修复它。

主要问题在于此行:

 case object Nothing extends Maybe[Nothing](Nothing)

首先(如前所述)您不应该将您的对象命名为 Nothing。其次,您将对象设置为扩展 Maybe[Nothing]。 Nothing 不能有任何实际值,所以你不能将它用作对象。此外,您不能将对象本身用作构造函数参数,因为那样会导致循环行为。

您需要的是拥有一个底层类型(即所有 A 共有的类型)和该类型的对象。 Nothing 是底层类型但没有对象。

一个可能的解决方案是将自己限制在 AnyRef(即可为 null 的对象)并使用具有有效对象(null)的 Null 底部类型:

 sealed abstract class Maybe[+A <: AnyRef](x:A)
 case object None extends Maybe[Null](null)

这是对 Assaf Mendelson 的回答的一些澄清,但对于评论来说太大了。

case object Nothing extends Maybe[Nothing](Nothing)

Scala 对类型和值有单独的命名空间。 case object Nothing中的Nothing是一个值。 Nothing in Maybe[Nothing] 是一种类型。由于您没有定义名为 Nothing 的类型,它指的是自动导入的 scala.Nothing 并且您必须将此类型的值作为参数传递。根据定义,它没有值,但例如case object Nothing extends Maybe[Nothing](throw new Exception) 会编译,因为 throw 表达式的类型是 Nothing。相反,您传递值 Nothing,即您正在定义的值 case object;它的类型写成 Nothing.type.

How do I pass Nothing instead of Nothing.type?

好像没有办法啊。 正如它在 http://www.scala-lang.org/api/2.9.1/scala/Nothing.html 中所说:

there exist no instances of this type.