Non è possibile confrontare i tipi direttamente, perché non c'è nulla da confrontare (in fase di esecuzione, a causa di erasure). Si potrebbe lavorare su una rappresentazione della classe:
trait TraitA { }
trait TraitB { }
class ClassA extends TraitA { }
class ClassB extends TraitB { }
def myFunc[T](clazz: Class[T]) = {
if (classOf[TraitA] isAssignableFrom clazz) println("A")
else if (classOf[TraitB] isAssignableFrom clazz) println("B")
else println("?")
}
scala> myFunc(classOf[ClassA])
A
scala> myFunc(classOf[String])
?
oppure si può abbinare modello sul istanze della classe:
def myFunc2[T](t: T) = t match {
case _: TraitA => println("A")
case _: TraitB => println("B")
case _ => println("?")
}
scala> myFunc2(new ClassA)
A
scala> myFunc2(Some(5))
?
È anche possibile utilizzare il primo approccio in modo sintatticamente meno invadente via classe manifesta:
def myFunc3[T](implicit mf: ClassManifest[T]) = {
val clazz = mf.erasure
if (classOf[TraitA] isAssignableFrom clazz) println("A")
else if (classOf[TraitB] isAssignableFrom clazz) println("B")
else println("?")
}
scala> myFunc3[ClassA]
A
scala> myFunc3[String]
?
ed è possibile scegliere diversi tipi di spedizione anche se il if/else diventa wieldy:
Si noti che qualsiasi codice generico che si utilizza da questo dovrà avere un manifest di classe disponibile (sia come parametro implicito o in stenografia, [T: ClassManifest]
.
fonte
2011-03-30 15:05:22
Ho effettivamente trovato 2 modi che funzionano bene nel mio caso: 1) classOf [TraitA] isAssignableFrom come hai suggerito 2) if (mf <:
codefly
+1: all'inizio mi sono irritato sia con la tua risposta sia con Scala ("Non puoi confrontare i tipi direttamente, perché non c'è ** nulla * * lì per confrontare "... C'è un ** tipo **, e un tipo è sicuramente qualcosa. Avresti dovuto scrivere" non c'è alcun * valore * "IMHO). Ma poi hai spiegato dei manifesti di classe, e questo è stato il colpo. Quindi grazie! – rsenna
@rsenna - Con "non c'è nulla" intendevo dire che non c'è niente lì _at runtime_ perché 'T' sta solo dicendo al compilatore come dovrebbe mantenere i tuoi tipi direttamente in fase di compilazione. Quindi in realtà ... un tipo generico è, in fase di esecuzione, nulla. È andato. ("Tipo cancellato.") I manifest forniscono un modo per fornire informazioni in fase di compilazione in fase di runtime. ('ClassTag' o' TypeTag' è il nuovo modo di farlo in 2.10, anche se il vecchio modo funziona ancora.) Comunque, felice che tu l'abbia trovato utile anche se il mio fraseggio non era molto delicato! –