Scala中如何实现Case Class类型的泛型及自定义类型模式匹配?
Scala Case Class 类型模式匹配解决方案
问题1:匹配任意泛型参数的Option、List或Map
直接用typeOf[Option[_]]做模式匹配无法生效,因为它是存在类型,而具体泛型实例(比如Option[String])的类型对象和typeOf[Option[_]]并不严格相等。正确思路是通过**类型构造器(typeConstructor)**匹配——类型构造器是泛型类型去掉参数后的核心部分,比如Option[String]和Option[Int]的typeConstructor完全一致。
示例代码修改如下:
import scala.reflect.runtime.universe._ // 预定义各泛型类型的构造器 val optConstructor = typeOf[Option[_]].typeConstructor val listConstructor = typeOf[List[_]].typeConstructor val mapConstructor = typeOf[Map[_, _]].typeConstructor typeOf[A].members.filter(!_.isMethod).map(_.typeSignature).foreach { case t if t =:= typeOf[Int] => println("int") case t if t =:= typeOf[String] => println("string") // 匹配任意泛型参数的Option case t if t.typeConstructor =:= optConstructor => println(s"Option[${t.typeArgs.head.typeSymbol.name}]") // 匹配任意泛型参数的List case t if t.typeConstructor =:= listConstructor => println(s"List[${t.typeArgs.head.typeSymbol.name}]") // 匹配任意泛型参数的Map case t if t.typeConstructor =:= mapConstructor => println(s"Map[${t.typeArgs(0).typeSymbol.name}, ${t.typeArgs(1).typeSymbol.name}]") // 其他逻辑... }
问题2:匹配所有自定义类型
自定义类型的核心特征是不属于Scala/Java标准库,且为用户自定义类(非原始类型、非标准库容器)。可以通过类型符号(typeSymbol)的包名、类属性判断:
示例代码补充:
typeOf[A].members.filter(!_.isMethod).map(_.typeSignature).foreach { // ...前面的匹配逻辑... case t if t.typeSymbol.isClass => val cls = t.typeSymbol.asClass // 排除原始类型、数组、标准库包下的类型 val isStandardType = cls.isPrimitive || cls.isArray || List("scala", "java", "javax", "sun").contains(cls.fullName.split("\\.").head) if (!isStandardType) { println(s"custom type: ${cls.fullName}") } else { println(s"standard type: ${cls.fullName}") } // 兜底匹配剩余类型 case t => println(s"other type: ${t.typeSymbol.name}") }
额外说明
- 若需仅匹配自定义case class,可添加
cls.isCaseClass条件; - 处理嵌套泛型(比如
List[Option[Int]])时,可递归检查类型参数的构造器。
内容的提问来源于stack exchange,提问作者Lyashko Kirill
相关产品推荐
相关产品推荐

