我可以在Scala中使用Enumerations作为类型参数吗?

时间:2016-10-24 04:45:45

标签: scala

我想使用Enumeration作为类型参数,编译器让我感到悲伤。

object VehicleClass extends Enumeration {
  type VehicleClass = Value
  val Land, Air, Sea = Value
}
import VehicleClass._

trait Vehicle[K <: VehicleClass] { val kind: K }
case class Car(passengers: Int) extends Vehicle[Land] { val kind: Land }

编译抱怨:

[error] /Users/me/test/scala/co.blocke.scalajack/json/test.misc/Greg.scala:18: not found: type Land
[error] case class Car(passengers: Int) extends Vehicle[Land] { val kind: Land }
[error]                                                 ^
[error] /Users/me/test/scala/co.blocke.scalajack/json/test.misc/Greg.scala:18: not found: type Land
[error] case class Car(passengers: Int) extends Vehicle[Land] { val kind: Land }
[error]                                                                   ^

如何做到这一点?

2 个答案:

答案 0 :(得分:2)

你可以写

case class Car(passengers: Int) extends Vehicle[Land.type] { 
  val kind: Land.type = Land 
}

Land.typeLand单例类型,即唯一值为Land的类型(不包括null)。

答案 1 :(得分:1)

Alexey为使用scala.Enumeration

提供了正确的答案

我会使用ADT而不是我认为已弃用的枚举来解决此问题。 (见http://underscore.io/blog/posts/2014/09/03/enumerations.html

以下是使用ADT的解决方案

// Using an abstract class makes accessing things in VehicleClass companion 
// object nicer
sealed abstract class VehicleClass

case object Land extends VehicleClass
case object Air extends VehicleClass
case object Sea extends VehicleClass

trait Vehicle[K <: VehicleClass] { val kind: K }
case class Car(passengers: Int) extends Vehicle[Land.type] { val kind = Land }

我会稍微简化一下这段代码,因为通常看不到要求使trait Vehicle通用。这增加了什么额外的安全性?我通常会将特性简化为

trait Vehicle { val kind: VehicleClass }

(我可以看到Vehicle泛型的唯一原因是为Vehicle[Land]定义类型类实例,而不是Vehicle[Land]的所有类型,但是{{1}可能需要更多成员。)