2013-06-17 3 views
5

Ich muss eine Musterübereinstimmung auf Klassen tun. Das Problem ist, dass ich einige Probleme mit einem Long habe.Scala: Wie Muster übereinstimmen scala.Long und java.lang.Long

Ich muss scala.Long und java.lang.Long in der gleichen Weise behandeln, aber warum muss ich sie beide in Fällen erklären? Hier

ein Beispiel:

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) 

Gibt es einen Weg, um sie gleich zu behandeln, ohne eine Instanz, die aber nur die Klasse?

Antwort

3

Der Grund dafür ist, dass java.lang.Long und Long verschiedene Klassen sind. In Java gibt es einen Unterschied zwischen java.lang.Long.class und Long.TYPE. In ähnlicher Weise sind in Scala classOf[Long] und classOf[java.lang.Long] unterschiedlich.

Wenn Sie Muster auf Klassen Spiel zu wollen, können Sie Helfer unapply Methoden für das Erstellen:

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

Im Allgemeinen werden Sie classOf[Long] und classOf[java.lang.Long] separat zu behandeln haben. Vielleicht, wenn Sie beschreiben, was Sie damit tun müssen, können wir eine bessere Lösung für Ihre spezifische Aufgabe finden.

4

Es sollte sofort arbeiten:

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 

Es war mir nicht klar, dass Sie Klassen statt Instanz übereinstimmen soll. Ich bin mir nicht sicher, ob ich verstehe, was du willst. So was?

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 

Oder als Mustervergleich:

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

Nur wenn ich den Wert habe! Ich brauche das, um zu funktionieren, wenn ich nur die Klasse habe, wie ich in der Frage gesagt habe: "Gibt es einen Weg, sie gleich zu behandeln, ohne eine Instanz zu haben, sondern nur die Klasse?" – maklemenz

+1

@mklemenz Sie würden gut bedient, um Ihre Beispiele auf genau das zu beschränken, was Sie wollen. Die Mehrheit (2/3) Ihrer Beispielmethoden haben den Wert, nur einer hat nur die Klasse. –

+0

Ich habe die Frage bearbeitet – maklemenz