Как я могу сравнить непредставленные Generics абстрактного WeakTypeTag - PullRequest
1 голос
/ 02 июля 2019

Мне нужно проверить тип любого объекта и получить соответствующий объект. Тем не менее, T не может быть решена путем передачи его в нормальный функциональный параметр. Вам нужно сравнивать, пока все параметры типа не совпадут.

trait Wrap[T]

trait Interface
trait InterfaceA extends Interface
trait InterfaceB extends Interface

object InterfaceAImpl extends Wrap[InterfaceA] with Candidate
object InterfaceBImpl extends Wrap[InterfaceB] with Candidate

trait Mediate[T <: Interface] {
  val t: T = get[Wrap[T]]
}

object A extends Mediate[InterfaceA]
object B extends Mediate[InterfaceB]
def get[T: c.WeakTypeTag](c: blackbox.Context): c.Expr[Option[T]] = {
    import c.universe._

    // Find an object that mixes in a specific interface
    // Suppose that the result is [[object A]] and [[object B]]
    val detected: List[Symbol] = new CandidateExtractor[c.type](c).run[Candidate]

    // This result is
    // "InterfaceAImpl =:= Wrap[T]"
    // "InterfaceBImpl =:= Wrap[T]"
    // When called from A, it expects Wrap[InterfaceA] instead of Wrap[T]
    detected.foreach(x => println(s"${x.typeSignature} =:= ${weakTypeOf[T]}"))

    // Find objects that inherits Wrap [T] among objects that inherit a specific interface
    val r = detected.collectFirst {
      // Wrap[InterfaceA] and Wrap[T] are compared, so all false.
      case x if x.typeSignature =:= weakTypeOf[T] => x
    }

    c.Expr[Option[T]](
      q"$r"
    )
  }

Есть ли способ сравнить наследственные отношения, в том числе дженерики?






Для второй попытки

В результате я хочу ...

  1. object A s t: T = InterfaceAImpl, поскольку он наследует Wrap[InterfaceA]
  2. object B s t: T = InterfaceBImpl, потому что он наследует Wrap[InterfaceB]

Значит, <:<(typeOf[Wrap[_]) недействительно.
Должно быть <:<(Wrap[_])
и baseClasses.find(Wrap[_]).typeArgs.contains(T (is InterfaceA or InterfaceB))

1 Ответ

0 голосов
/ 04 июля 2019

Попробуйте

List(typeOf[Wrap[_]].typeSymbol, typeOf[Candidate].typeSymbol).forall(x.typeSignature.baseClasses.contains)

или

List(typeOf[Wrap[_]].typeSymbol, typeOf[Candidate].typeSymbol).forall(x.typeSignature.baseType(_) match { case _ : TypeRef => true; case NoType => false })
...