2013-06-17 8 views
5

Ho bisogno di fare un pattern match su Classes. Il problema è che ho alcuni problemi che corrispondono a Long.Scala: come abbinare scala.Long e java.lang.Long

Ho bisogno di gestire scala.Long e java.lang.Long allo stesso modo, ma perché devo dichiararli entrambi nei casi?

Ecco un esempio:

def test(typ: Class[_]) { 
    typ match { 
     case q if q == classOf[Long] => println("scala long...") 
    } 
    } 

    val scalaLongField: java.reflect.Field = ...... 
    val javaLongField: java.reflect.Field = ...... 
    test(scalaLongField.getType) // prints "scala long..." 
    test(javaLongField.getType) // scala.MatchError: class java.lang.Long (of class java.lang.Class) 

Esiste un modo per gestire loro la stessa senza avere un grado, ma solo la classe?

risposta

3

La ragione è che java.lang.Long e Long sono classi diverse. In Java, c'è una differenza tra java.lang.Long.class e Long.TYPE. Allo stesso modo, in Scala, classOf[Long] e classOf[java.lang.Long] sono diversi.

Se si desidera pattern match sulle classi, è possibile creare aiutante unapply metodi per che:

object ScalaLong { 
    // Internal helper: 
    private def matchClass[T](c: Class[_], as: Class[T]): Option[Class[T]] = 
    if (as.isAssignableFrom(c)) Some(as) 
    else None; 

    // Matches wrapped Long classes. 
    object LongObject { 
    def unapply(c: Class[_]): Option[Class[java.lang.Long]] = 
     matchClass(c, classOf[java.lang.Long]); 
    } 
    // Matches primitive long classes. 
    object LongPrim { 
    def unapply(c: Class[_]): Option[Class[Long]] = 
     matchClass(c, classOf[Long]); 
    } 

    // -- Test: 

    def check(clz: Class[_]) = 
    clz match { 
     case LongPrim(c) => println("Long primitive: " + c); 
     case LongObject(c) => println("Long object: " + c); 
     case _    => println("Other: " + clz); 
    } 


    class Example { 
    val l1: scala.Long = 1L; 
    val l2: java.lang.Long = 1L; 
    val l3: java.lang.Integer = 1; 
    } 

    def main(argv: Array[String]) { 
    for(name <- Seq("l1", "l2", "l3")) 
     check(classOf[Example].getMethod(name).getReturnType()); 
    } 
} 

In generale, si dovrà trattare classOf[Long] e classOf[java.lang.Long] separatamente. Forse, se descrivi cosa devi fare con loro, possiamo trovare una soluzione migliore per il tuo compito specifico.

4

Dovrebbe funzionare subito:

object LongTest { 
    def test(value: Any): Boolean = value match { 
    case l: Long => true 
    case _ => false 
    } 

    def run() { 
    println(test(1L)) 
    println(test(new java.lang.Long(1L))) 
    } 
} 

LongTest.run() // true and true 

non era ovvio per me che si desidera abbinare classi invece di esempio. Non sono sicuro di capire cosa vuoi veramente. Come questo?

object LongTest { 
    def test(clazz: Class[_]): Boolean = 
    clazz == classOf[Long] || clazz == classOf[java.lang.Long] 

    def run() { 
    println(test(1L.getClass)) 
    println(test(new java.lang.Long(1L).getClass)) 
    } 
} 

LongTest.run() // true and true 

O come un pattern match:

def test(clazz: Class[_]): Boolean = clazz match { 
    case q if q == classOf[Long] || q == classOf[java.lang.Long] => true 
    case _ => false 
    } 
+0

Solo se ho il valore! Ho bisogno di questo per funzionare quando ho solo la classe, come ho detto nella domanda: "C'è un modo per gestirli allo stesso modo senza avere un'istanza ma solo la classe?" – maklemenz

+1

@mklemenz ti farebbe bene a restringere i tuoi esempi esattamente a ciò che desideri. La maggior parte (2/3) dei metodi di esempio ha il valore, solo una ha solo la classe. –

+0

Ho modificato la domanda – maklemenz

Problemi correlati