Supponendo che ho una superclasse Generico:In Scala Reflection, Come ottenere un parametro di tipo generico di una sottoclasse di calcestruzzo?
class GenericExample[T](
a: String,
b: T
) {
def fn(i: T): T = b
}
e una sottoclasse concreta:
case class Example(
a: String,
b: Int
) extends GenericExample[Int](a, b)
voglio ottenere il parametro di tipo di funzione "Fn" di Scala riflessione, in modo da selezionare e filtrare attraverso i suoi membri:
import ScalaReflection.universe._
val baseType = typeTag[Example]
val member = baseType
.tpe
.member(methodName: TermName)
.asTerm
.alternatives
.map(_.asMethod)
.head
val paramss = member.paramss
val actualTypess: List[List[Type]] = paramss.map {
params =>
params.map {
param =>
param.typeSignature
}
}
mi aspettavo scala di darmi il risultato corretto, che è List(List(Int))
, invece solo io g ot il generico List(List(T))
Crunching attraverso il documento ho scoperto che typeSignature è il colpevole:
* This method always returns signatures in the most generic way possible, even if the underlying symbol is obtained from an
* instantiation of a generic type.
E mi suggerisce di utilizzare l'alternativa:
def typeSignatureIn(site: Type): Type
Tuttavia, dal momento che di classe Esempio c'è più generico, non c'è modo di ottenere il sito da typeTag [Esempio], qualcuno può suggerirmi come ottenere typeOf [Int] dato solo typeTag [Example]? O non c'è modo di farlo e devo tornare alla riflessione Java?
Grazie mille per il vostro aiuto.
UPDATE: Dopo qualche prova pratica ho scoperto che anche MethodSymbol.returnType non funziona come previsto, il codice seguente:
member.returnType
anche produrre T
, annd non può essere corretto da asSeenFrom, come il seguente codice non cambia il risultato:
member.returnType.asSeenFrom(baseType.tpe, baseType.tpe.typeSymbol.asClass)
Prima ancora di aver letto la tua domanda. Durante tutta la mia esperienza con scala, uno dei suoi concetti base è di delegare il più possibile al compilatore. Quindi la riflessione non è una di quelle cose che dovresti fare in scala. Tuttavia è possibile utilizzare Macro o limiti di contesto (Manifests e ClassManifests) – caeus
È Manifest in corso di deprecazione? E ClassManifest ridenominato in ClassTag? Spero di poter almeno ottenere il ClassTag cancellato dal metodo, ma ancora non è in grado di farlo. – tribbloid