在Scala2.13中,我为所有类型定义了一些操作,扩展了一些密封的特征EnumType
。我让它工作了,但我希望getTypeClass
函数不依赖于扩展EnumType
的具体类型。现在,每当EnumType
发生更改并添加或删除某些模式时,我都必须访问此函数。有没有一种方法可以获得EnumType
类型的Operation
类型类的示例,而不需要对所有类型进行模式匹配?
sealed trait EnumType
case object Add10 extends EnumType
case object Add50 extends EnumType
trait Operation[+T] {
def op(a: Int): Int
}
implicit val add10: Operation[Add10.type] = (a: Int) => a + 10
implicit val add50: Operation[Add50.type] = (a: Int) => a + 50
def getTypeClass(enumType: EnumType): Operation[EnumType] = {
// I need to modify this pattern matching
// every time EnumType changes
enumType match {
case Add10 => implicitly[Operation[Add10.type]]
case Add50 => implicitly[Operation[Add50.type]]
}
// I'd wish it could be done with without pattern matching like (it does not compile):
// implicitly[Operation[concrete_type_of(enumType)]]
}
// value of enumType is dynamic - it can be even decoded from some json document
val enumType: EnumType = Add50
println(getTypeClass(enumType).op(10)) // prints 60
编辑我希望不使用EnumType
的显式子类型(在本例中使用circe
来解码json)的调用方式:
case class Doc(enumType: EnumType, param: Int)
implicit val docDecoder: Decoder[Doc] = deriveDecoder
implicit val enumTypeDecoder: Decoder[EnumType] = deriveEnumerationDecoder
decode[Doc]("""{"enumType": "Add10", "param": 10}""").map {
doc =>
println(getTypeClass(doc.enumType).call(doc.param))
}
2条答案
按热度按时间waxmsbnn1#
由于您只知道静态
enumType
只有EnumType
类型,并且希望基于enumType
的运行时值/运行时类进行匹配,因此您必须使用某种反射:或
或
因为所有对象都是在编译时定义的,所以我想宏更好。
Covariant case class mapping to its base class without a type parameter and back
Getting subclasses of a sealed trait
Iteration over a sealed trait in Scala?
您甚至可以创建一个宏白盒,然后在宏中使用runtime reflection可以静态地使用
Add50
类型(如果在宏展开时知道类)How to accept only a specific subtype of existential type?
In a scala macro, how to get the full name that a class will have at runtime?
iq0todco2#
事实上,您甚至根本不需要
getTypeClass
:我在上面使用的
Foo : Bar
表示法相当于:请注意,您实际上并没有在任何地方使用
Add50
和Add10
的示例。它们可能只是特征而不是物体(IMO,这更能反映意图):