Je veux coder un constructeur de type simple dans scala. Quoi qu'il en soit, le constructeur de caractères fonctionne comme un charme. Je veux enregistrer dans le constructeur de type une classe.Étrange comportement de la macro scala lors de la vérification du type abstrait?
A exécution il n'y a pas de problème pour que:
if (classSymbol.isAbstract) throw new IllegalArgumentException("Provided class is abstract")
tagger la méthode avec un attribut typetag , si scala n'Erasure pas le temps lors de la compilation.
def createInstance[T: TypeTag]: T
De toute façon, cela fonctionne. Je ne préfère pas de cette façon, car l'utilisateur peut entrer une classe abstraite et vouloir le créer. Je ne veux pas vérifier l'exception d'argument à l'exécution.
Donc, je pensais que ce serait vraiment cool de vérifier le bon type pendant temps de compilation. Ce est le code complet de la fonction macro :
object ClassCheckMacro {
def checkClass[T](x: T): T = macro checkClassImpl[T]
def checkClassImpl[T: c.WeakTypeTag](c: blackbox.Context)(x: c.Tree) = {
import c.universe._
val symbol = weakTypeOf[T].typeSymbol
if (symbol.isAbstract) {
c.abort(c.enclosingPosition, s"${symbol.fullName} must be a class")
} else {
c.Expr(q"($x)")
}
}
}
evertime J'utilise cette macro, je reçois le message d'abort "doit être une classe". Peu importe s'il s'agit d'un type de classe ou d'un type abstrait. Utilisation:
val typeInfo = typeOf[T]
val classSymbol = typeInfo.typeSymbol.asClass
ClassCheckMacro.checkClass(classSymbol)
Existe-t-il des conseils pour ce comportement "étrange"?
Avez-vous l'intention 'checkClass (nouveau C)'? –
Oui, une sorte de ça. pour 'new C' je dois mettre le typeSymbol, parce que vous ne pouvez pas créer une nouvelle instance d'un type générique;) –
Je pense que vous ne comprenez pas comment l'invoquer. Étant donné 'class C', essayez' checkClass [C] (null) ', par exemple. –