scala 如何使用继承和模板的模式匹配 class
scala how to use pattern matching with inheriance and templated class
我们公司使用的数据结构如下所示:
trait Resource
case class templatedResource[T](t: T) extends Resource
case class BParameter()
case class CParameter()
object B {
type Resource = templatedResource[BParameter]
}
object C {
type Resource = templatedResource[CParameter]
}
在某些时候,给定一些未知的 Resource
s 我们想使用模式匹配来确定它们的内部类型并启动一些不同的处理。
但是由于类型擦除,简单的模式匹配不起作用。所以我们尝试使用 TypeTags
,但没有成功:
import scala.reflect.runtime.universe._
object Service {
def process(resource: Resource)(implicit tag: WeakTypeTag[Resource]) = {
(tag.tpe, resource) match {
case (t, b: B.Resource) if t =:= typeOf[B.Resource] =>
println("b !!")
case (t, c: C.Resource) if t =:= typeOf[C.Resource] =>
println("c !!")
case _ =>
throw new IllegalStateException(s"Unexpected resource type")
}
}
}
val bParam = BParameter()
val bResource: B.Resource = templatedResource(bParam)
Service.process(bResource)
// throws java.lang.IllegalStateException: Unexpected resource type
// at Service$.process(<console>:26)
似乎 t =:= typeOf[B.Resource]
总是错误的,因为 t
只知道 Resource
特征 ( t =:= typeOf[Resource]
) 而不知道具体实现。
我怎样才能让这个模式匹配起作用?
您应该将您的擦除类型参数修正为一些新类型。类型别名不是新类型,只是当前类型的附加名称。
你可以这样做:
trait Resource
class templatedResource[T](t: T) extends Resource
case class BParameter()
case class CParameter()
object B {
case class Resource(val b: BParameter) extends templatedResource[BParameter](b)
}
object C {
type Resource = templatedResource[CParameter]
}
def process(r: Resource) = {
r match {
case a: B.Resource => true
}
}
process(B.Resource(BParameter()))
如果您需要保留创建语法 val bResource: B.Resource = templatedResource(bParam)
以消除 end-user 的样板 - 您应该使用此类创建来定义函数。消除实施
函数的样板 - 我猜你可以使用宏或类似 shapeless 的东西。
我们公司使用的数据结构如下所示:
trait Resource
case class templatedResource[T](t: T) extends Resource
case class BParameter()
case class CParameter()
object B {
type Resource = templatedResource[BParameter]
}
object C {
type Resource = templatedResource[CParameter]
}
在某些时候,给定一些未知的 Resource
s 我们想使用模式匹配来确定它们的内部类型并启动一些不同的处理。
但是由于类型擦除,简单的模式匹配不起作用。所以我们尝试使用 TypeTags
,但没有成功:
import scala.reflect.runtime.universe._
object Service {
def process(resource: Resource)(implicit tag: WeakTypeTag[Resource]) = {
(tag.tpe, resource) match {
case (t, b: B.Resource) if t =:= typeOf[B.Resource] =>
println("b !!")
case (t, c: C.Resource) if t =:= typeOf[C.Resource] =>
println("c !!")
case _ =>
throw new IllegalStateException(s"Unexpected resource type")
}
}
}
val bParam = BParameter()
val bResource: B.Resource = templatedResource(bParam)
Service.process(bResource)
// throws java.lang.IllegalStateException: Unexpected resource type
// at Service$.process(<console>:26)
似乎 t =:= typeOf[B.Resource]
总是错误的,因为 t
只知道 Resource
特征 ( t =:= typeOf[Resource]
) 而不知道具体实现。
我怎样才能让这个模式匹配起作用?
您应该将您的擦除类型参数修正为一些新类型。类型别名不是新类型,只是当前类型的附加名称。
你可以这样做:
trait Resource
class templatedResource[T](t: T) extends Resource
case class BParameter()
case class CParameter()
object B {
case class Resource(val b: BParameter) extends templatedResource[BParameter](b)
}
object C {
type Resource = templatedResource[CParameter]
}
def process(r: Resource) = {
r match {
case a: B.Resource => true
}
}
process(B.Resource(BParameter()))
如果您需要保留创建语法 val bResource: B.Resource = templatedResource(bParam)
以消除 end-user 的样板 - 您应该使用此类创建来定义函数。消除实施
函数的样板 - 我猜你可以使用宏或类似 shapeless 的东西。