I'm starting a Scala role in a few weeks yet I haven't written any Scala before (yes, my future employers know this), although I've written a lot of C# and Haskell. Anyway I was skimming through the Scala 3 book, and found this example:
enum Option[+T]:
case Some(x: T)
case None
Run Code Online (Sandbox Code Playgroud)
Which apparently dusugars into:
enum Option[+T]:
case Some(x: T) extends Option[T]
case None extends Option[Nothing]
Run Code Online (Sandbox Code Playgroud)
My two questions are:
Some
by default extend Option[T]
whereas None
extends Option[Nothing]
?Option
. I would define it like this:enum Option[+T]:
case Some(x: T) extends Option[T]
case None extends Option[T]
Run Code Online (Sandbox Code Playgroud)
Indeed with None
extending Option[None]
wouldn't this fail?
Option[string] x = None;
Run Code Online (Sandbox Code Playgroud)
As Option[T]
is covariant in T
and None
is not a subtype of string
?
I'm missing something quite fundamental here I'm sure.
关于枚举脱糖工作原理的一个很好的来源是Issue #1970的原始提案。
该页面上与您的问题相关的部分标题为“脱糖”。我们来看看你的Option
定义。
enum Option[+T]:
case Some(x: T)
case None
Run Code Online (Sandbox Code Playgroud)
Some
是带有类型参数的枚举下的参数化情况,因此规则#4适用
如果 E 是具有类型参数 Ts 的枚举类,则其伴生对象中的 case 不带 extends 子句
Run Code Online (Sandbox Code Playgroud)case C <params> <body>
...
对于 C 没有类型参数的情况,假设 E 的类型参数是
Run Code Online (Sandbox Code Playgroud)V1 T1 > L1 <: U1 , ... , Vn Tn >: Ln <: Un (n > 0)
其中每个方差 Vi 是“+”或“-”。然后案件扩大到
Run Code Online (Sandbox Code Playgroud)case C <params> extends E[B1, ..., Bn] <body>
因此,正如您所期望的,您的Some
案例有一个extends
条款。Option[T]
然后规则#5 为我们提供了实际的案例类别。
另一方面,None
出于同样的原因,您的不使用类型参数,因此结果基于方差。
T
是不变的,我们必须明确指定一个extends
子句T
是协变的,我们得到Nothing
T
是逆变的,我们得到Any
你T
是协变的,所以我们扩展,记住它是for any 的Option[Nothing]
子类型。因此,你的赋值(记住,在 Scala 中,我们使用/来声明变量,而不仅仅是类型名称)Option[S]
S
val
var
val x: Option[String] = None;
Run Code Online (Sandbox Code Playgroud)
None
是类型 的值None.type
,它扩展了Option[Nothing]
. Option[Nothing]
是 的子类型Option[String]
因为Nothing
是 的子类型String
。这样任务就成功了。
Nil
这与扩展(空列表)的原因相同List[Nothing]
。我可以构造一个Nil
具有具体类型( 的子类型List[Nothing]
)的 ,然后我可以在它前面添加我想要的任何内容。结果列表不再是List[Nothing]
; 1 +: Nil
是 aList[Int]
和"a" +: Nil
是 a List[String]
,但重点是,它Nil
可以来自我的程序中的任何位置,我们不必预先决定我们希望它是什么类型。我们不能(安全地)在可变数据类型上使用协方差,所以这一切都有效,因为List
和Option
是不可变的。可变集合的ArrayBuffer
类型参数是不变的。(注意:Java 的内置数组是协变的,这是不健全的并且会导致各种问题)