scala - scala列表与泛型的模式匹配
问题描述
我有一堂课
case class MyClass[T](values: List[T])
我正在尝试创建一个函数,该函数将根据 T 的类型返回一个值
def myFunc: T = values match {
case v: List[Boolean] => false
case v: List[MyType] => MyType.defaultVal
case _ => throw new Exception("unsupported type")
}
但是,我得到编译错误:
Boolean 类型的表达式不符合预期的 T 类型
MyType.defaultVal.type 类型的表达式不符合预期的类型 T
我想我可以通过创建一个抽象类和子类来解决这个问题,但我不想这样做。有没有其他方法可以解决这个问题?
解决方案
问题是模式匹配主要在运行时执行,类型在编译时解析。因为类型擦除case v: List[Boolean] => ???
并不比case v: List[_] => ???
. 在行case v: List[Boolean] => ...
编译器不知道T =:= Boolean
。模式匹配不能从不同的情况下返回不同的类型。
因此,您可以使用类型标签进行模式匹配和强制转换
case class MyClass[T](values: List[T]) {
import reflect.runtime.universe.{TypeTag, typeOf}
def myFunc(implicit typeTag: TypeTag[T]): T = values match {
case v: List[Boolean] if typeOf[T] <:< typeOf[Boolean] => false.asInstanceOf[T]
case v: List[MyType] if typeOf[T] <:< typeOf[MyType] => MyType.defaultVal.asInstanceOf[T]
case _ => throw new Exception("unsupported type")
}
}
或者使用类型类(或多态函数)更安全地执行此操作
case class MyClass[T](values: List[T]) {
def myFunc(implicit myFuncInstance: MyFunc[T]): T = myFuncInstance(values)
}
trait MyFunc[T] {
def apply(values: List[T]): T
}
object MyFunc {
implicit val booleanMyFunc: MyFunc[Boolean] = new MyFunc[Boolean] {
override def apply(values: List[Boolean]): Boolean = false
}
implicit val myTypeMyFunc: MyFunc[MyType] = new MyFunc[MyType] {
override def apply(values: List[MyType]): MyType = MyType.defaultVal
}
}
推荐阅读
- c# - 同一个 dll 中包含的别名程序集
- python - 为什么我的列名在我没有分配的时候变成了数字?
- javascript - How do i make my discord bot type in a specific channel while someone is typing in the bots dms?
- html - 如何在所有页面完全加载之前隐藏页面的各个部分
- javascript - 如何在 jQuery 中将选定的值作为参数传递?
- elixir - 僵尸进程或类似的东西?
- typescript - “永不扩展”是做什么用的?
- android - Hilt中组件的作用是什么?
- php - 如何纠正apiato项目中没有现有目录的错误?
- go - 如何在 Golang 中计算 int 值和 float64 值?