【问题标题】:scala reflection, get type parameter of super classscala反射,获取超类的类型参数
【发布时间】:2018-09-25 08:56:29
【问题描述】:

如何从子类中获取超类类型参数的具体类型?

假设我有一个通用超类、一个中间类和一个子类如下:

class SuperClass[A, B]
class IntClass[A] extends SuperClass[A, Int]
class MyClass extends SuperClass[String, Int]

我想要一个返回 SuperClass 类型参数的函数“getTypeArgs”:

val superClassType = typeOf[SuperClass[_, _]]

val superClassOfStringInt = appliedType(superClassType.typeConstructor, typeOf[String], typeOf[Int])
getTypeArgs(superClassOfStringInt, superClassType)
// [TEST1] should return List(String, Int)

getTypeArgs(typeOf[MyClass], superClassType)
// [TEST2] should return List(String, Int)

val intClassOfLong = appliedType(typeOf[IntClass[_]].typeConstructor, typeOf[Long])
getTypeArgs(intClassOfLong, superClassType)
// [TEST3] should return List(Long, Int)

我已经尝试过In Scala Reflection, How to get generic type parameter of a concrete subclass?的解决方案:

def getTypeArgs(t: Type, fromType: Type): List[Type] = {
  internal
    .thisType(t.dealias.typeSymbol)
    .baseType(fromType.typeSymbol.asClass)
    .typeArgs
}

它适用于 TEST2,但 TEST1 返回 List(A, B) 而 TEST3 返回 List(A, Int)。

我可以通过添加一个测试来检查符号是否相等来修复 TEST1:

def getTypeArgs(t: Type, fromType: Type): List[Type] = {
  if (t.erasure.typeSymbol == fromType.typeSymbol)
    t.typeArgs
  else
    internal
      .thisType(t.dealias.typeSymbol)
      .baseType(fromType.typeSymbol.asClass)
      .typeArgs
}

我不知道如何让 TEST3 工作。

【问题讨论】:

  • 目标是什么?好像是个 XY 问题
  • 我在编写的 scala 宏中有几个用例。例如,我有一个构建者:class Builder[FROM, TO] extends (FROM => TO)。从构建器类型中,我的宏需要识别具体类型 FROM 并提取其字段(来自案例类的 primaryConstructor)。即使我给它一个 Builder 的子类,我的宏也必须工作。
  • 那还是没有说明目标,还是XY
  • 目标很简单。给定一个类型,我想检查该类型是否为Builder[_, _](由<:< 轻松完成),如果是,则获取Builder 的类型参数,即使输入类型是Builder 的子类型。
  • 这不是目标,而是手段

标签: scala generics reflection scala-reflect


【解决方案1】:

解决方案其实很简单:

def getTypeArgs(t: Type, fromType: Type): List[Type] = {
    t.baseType(fromType.typeSymbol).typeArgs
}

这个函数通过了所有的测试。

【讨论】:

    猜你喜欢
    • 2013-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-11
    • 2015-04-18
    • 2021-05-13
    相关资源
    最近更新 更多