2013-06-17 8 views
5

Muszę zrobić dopasowanie wzorca na zajęcia. Problem polega na tym, że mam kilka problemów pasujących do Long.Scala: Jak wzorować mecz scala.Long i java.lang.Long

Potrzebuję obsługiwać scala.Long i java.lang.Long w ten sam sposób, ale dlaczego muszę zadeklarować je oba w przypadkach?

Oto przykład:

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) 

Czy istnieje sposób, aby obsługiwać je tak samo, bez konieczności wystąpienia, ale po prostu klasę?

Odpowiedz

3

Powodem jest to, że java.lang.Long i Long są różne klasy. W języku Java występuje różnica między java.lang.Long.class i Long.TYPE. Podobnie w Scali, classOf[Long] i classOf[java.lang.Long] są różne.

Jeśli chcesz wzór spotkanie na zajęciach, można utworzyć pomocnika unapply metod, które:

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()); 
    } 
} 

Generalnie, trzeba traktować classOf[Long] i classOf[java.lang.Long] oddzielnie. Być może, jeśli opiszemy, co trzeba z nimi zrobić, możemy znaleźć lepsze rozwiązanie dla konkretnego zadania.

4

Powinien działać od razu:

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 

To nie było dla mnie oczywiste, że chcesz dopasować zajęcia zamiast instancji. Nie jestem pewien, czy rozumiem, czego tak naprawdę chcesz. Lubię to?

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 

lub jako wzór meczu:

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

Tylko jeśli mam wartość! Potrzebuję tego do pracy, kiedy mam tylko zajęcia, tak jak powiedziałem w pytaniu: "Czy istnieje sposób, aby poradzić sobie z nimi tak samo, nie mając instancji, ale tylko klasę?" – maklemenz

+1

@mklemenz dobrze byś służył do ograniczenia przykładów do dokładnie tego, co chcesz. Większość (2/3) Twoich przykładowych metod ma wartość, tylko jedna ma tylko klasę. –

+0

Edytowałem pytanie – maklemenz