如何在Scala中定义极限值的类型?

时间:2019-01-23 10:09:17

标签: scala

我需要限制函数的调用者仅使用字符串“ asc”或“ desc”,因此我想使用常量来定义类型。

使用打字稿时,我可以这样做:

function test(order: "asc" | "desc") {
    // ...
}

那么顺序只能是“ asc”或“ desc”。那么如何在Scala中定义order

2 个答案:

答案 0 :(得分:3)

sealed trait order
case object asc extends order
case object desc extends order

自动转换

您可以使用隐式转换将String自动转换为order

object order {
  implicit def string2order(s: String): order = s match {
    case "asc" => asc
    case "desc" => desc
  }
}

一旦定义好了,您就可以将String传递给采用order的方法,它将被自动转换。 (如果给出了无效的值,将显示MatchError

请注意,不建议以这种方式使用字符串;只需直接使用case对象即可获得更好的类型安全性。


请注意,我保留了orderascdesc的大小写以匹配您的问题,但是Scala约定是将大写字母用于类和对象的名称({{1 }},OrderAsc

答案 1 :(得分:2)

很遗憾,我们还没有这样的联合类型。尽管没有像您的示例afaik中那样用于单例类型,但它们被安排为有点。

采用这种密封性状等级的最常见方法

sealed trait Order
final case object Asc extends Order
final case object Desc extends Order

重要的是特征是最终的,而案例类/对象是最终的,以便编译器可以进行详尽性检查

val ord:Order = Asc
val ord2:Order = Desc

是仅有的两种可能的情况,因为特征和案例类/对象都无法进一步扩展。这意味着类型为Order的每个实例必须为AscDesc

ord match {
    case Asc => ???
    case Desc => ???
}

Order上进行模式匹配,然后执行任何操作

编辑:“匿名”方法是通过Either[A, B]数据类型,尽管这也需要使用单例类型(您可以通过诸如shapeless之类的某些库获得),或者您只是以Either[String, String]结尾,就是meh。