Scala runtime解析类型带type class约束的泛型调用问题咨询
解决方案
你之前的写法只保存了TypeTag这一个编译期证据,丢失了HasMoveCapability的隐式实例证据,所以编译器无法在调用doLogic时补全所需的隐式参数,导致编译失败。
核心思路
把doLogic所需的两个上下文约束(TypeTag[T] + HasMoveCapability[T])封装为一个可在运行时传递的实体,模式匹配仅需执行一次即可拿到所有需要的编译期证据,后续调用任意符合约束的函数都无需重复编写匹配逻辑。
步骤1:定义约束封装实体
import scala.reflect.runtime.universe.TypeTag // 原代码保留 trait HasMoveCapability[T] def doLogic[T: TypeTag: HasMoveCapability](): Unit = println(typeTag[T].tpe) case class Bird() object Bird { implicit val hasMoveCapability: HasMoveCapability[Bird] = new HasMoveCapability[Bird] {} } case class Lion() object Lion { implicit val hasMoveCapability: HasMoveCapability[Lion] = new HasMoveCapability[Lion] {} } // 新增:封装两个约束证据 trait MoveType[A] { def typeTag: TypeTag[A] def hasMoveCapability: HasMoveCapability[A] } object MoveType { // 给支持的类型提前创建封装实例 implicit val bird: MoveType[Bird] = new MoveType[Bird] { override def typeTag: TypeTag[Bird] = implicitly[TypeTag[Bird]] override def hasMoveCapability: HasMoveCapability[Bird] = implicitly[HasMoveCapability[Bird]] } implicit val lion: MoveType[Lion] = new MoveType[Lion] { override def typeTag: TypeTag[Lion] = implicitly[TypeTag[Lion]] override def hasMoveCapability: HasMoveCapability[Lion] = implicitly[HasMoveCapability[Lion]] } }
步骤2:仅编写一次输入解析逻辑
def resolveMoveType(input: String): MoveType[_] = input match { case "bird" => MoveType.bird case "lion" => MoveType.lion case other => throw new IllegalArgumentException(s"不支持的输入类型:$other") }
步骤3:给目标函数编写轻量适配层
每个需要动态调用的函数仅需编写一次适配,无需重复匹配逻辑:
// 适配原doLogic函数 def doLogic(moveType: MoveType[_]): Unit = { def helper[A](mt: MoveType[A]): Unit = doLogic[A]()(mt.typeTag, mt.hasMoveCapability) helper(moveType) } // 若有其他同约束函数,同理适配即可: // def doOtherLogic[T: TypeTag: HasMoveCapability](param: String): Unit = ??? // def doOtherLogic(moveType: MoveType[_], param: String): Unit = { // def helper[A](mt: MoveType[A]): Unit = doOtherLogic[A](param)(mt.typeTag, mt.hasMoveCapability) // helper(moveType) // }
步骤4:调用示例
val input: String = "bird" // 运行时动态获取的输入 val moveType = resolveMoveType(input) // 直接调用任意适配后的函数,无需再匹配 doLogic(moveType) // doOtherLogic(moveType, "测试参数")
维护扩展说明
- 新增支持的类型:仅需在
MoveType对象中新增对应类型的实例,同时在resolveMoveType的模式匹配中加一个分支即可 - 新增需要调用的函数:仅需新增一次适配逻辑,无需修改解析和匹配代码
内容的提问来源于stack exchange,提问作者Wassim Maaoui
相关产品推荐
相关产品推荐

