[英]Organizing Scala implicits associated with a type
我想介绍一些类型来表示较大类型的字段的可能值。 该字段必须能够与JSON编码/从JSON编码/解码,还必须能够写入/读取到数据库。
我还是Scala的新手,我想要的类型是总和类型Status = NotVerified | Correct | Wrong
Status = NotVerified | Correct | Wrong
Status = NotVerified | Correct | Wrong
。 由于我想与每个构造函数关联一个字符串表示形式,因此我创建了一个带有String
参数的密封案例类,然后创建了扩展该案例类的对象。 为了能够进行编码/解码,我还需要隐式,但是我不确定如何构造它。 我可以将它们放在对象内部的新对象中,如下所示:
sealed case class Status(name: String)
object Status {
object NotVerified extends Status("not_verified")
object Correct extends Status("correct")
object Wrong extends Status("wrong")
object implicits {
implicit val encodeStatusJson: Encoder[Status] =
_.name.asJson
implicit val decodeStatusJson: Decoder[Status] =
Decoder.decodeString.map(Status(_))
implicit val encodeStatus: MappedEncoding[Status, String] =
MappedEncoding[Status, String](_.name)
implicit val decodeStatus: MappedEncoding[String, Status] =
MappedEncoding[String, Status](Status(_))
}
}
…然后在需要的地方显式import
这些,但这很…显式。
组织这种类型+隐式集合的好方法是什么?
常用的方法是定义sealed trait
:
sealed trait Status {
def name: String
}
object Status {
case object NotVerified extends Status {
val name = "not_verified"
}
case object Correct extends Status {
val name = "correct"
}
case object Wrong extends Status {
val name = "wrong"
}
}
或一个sealed abstract class
,在当前的Scala版本中可能看起来更好:
sealed abstract class Status(val name: String)
object Status {
case object NotVerified extends Status("not_verified")
case object Correct extends Status("correct")
case object Wrong extends Status("wrong")
}
为了避免导入隐式,可以将它们直接放置在该类型的伴随对象中。 另请参阅问题Scala在哪里寻找隐式? 有关更多详细信息,特别是Type的Companion Objects部分。
是的,为这样的枚举定义隐式很容易重复。 您必须求助于反射或宏。 我建议使用Enumeratum库,该库也与Circe和Quill集成。 这是Circe的示例:
import enumeratum.values._
sealed abstract class Status(val value: String) extends StringEnumEntry {
def name: String = value
}
object Status extends StringEnum[Status] with StringCirceEnum[Status] {
val values = findValues
case object NotVerified extends Status("not_verified")
case object Correct extends Status("correct")
case object Wrong extends Status("wrong")
}
而且您可以使用它而无需显式定义任何编码器/解码器或从Status
导入任何内容:
scala> import io.circe.syntax._
scala> val status: Status = Status.Correct
status: Status = Correct
scala> status.asJson
res1: io.circe.Json = "correct"
scala> Decoder[Status].decodeJson(Json.fromString("correct"))
res2: io.circe.Decoder.Result[Status] = Right(Correct)
如果添加了apply
方法,则可以从String
创建适当的Status
,这将使Decoder
正常工作。 并将Status
抽象化
sealed abstract class Status(name: String)
object Status {
object NotVerified extends Status("not_verified")
object Correct extends Status("correct")
object Wrong extends Status("wrong")
def apply(name: String): Status = name match {
case "not_verified" => NotVerified
case "correct" => Correct
case _ => Wrong
}
}
我认为您现有的隐式函数仍然可以使用,但是我不知道那些特定的库...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.