2010-04-16 8 views
8

Hallo Kerl Scala ProgrammiererScala gewohnt Mustervergleich mit java.lang.String und Case-Klasse

Ich habe jetzt einige Monate mit Scala arbeiten, aber ich habe ein Problem mit einigen richtig grundlegenden Dingen, ich bin die Hoffnung, Sie wird mir dabei helfen.

case class PersonClass(name: String, age: Int) 

object CaseTester { 
def main(args:Array[String]) 
{ 
    val string = "hej" 
    string match { 
    case e:String => println(string) 
    case PersonClass => println(string) 
    } 
} 
} 

Wenn ich so mache ich Fehler:

pattern type is incompatible with expected type; 
found : object PersonClass 
required: java.lang.String 
case PersonClass => println(string) 

Und wenn ich dann die zweite Zeile in dem auf die folgende passende Muster ändern:

case e:PersonClass => println(string) 

ich dann bekommen der Fehler:

error: scrutinee is incompatible with pattern type; 
found : PersonClass 
required: java.lang.String 
case e:PersonClass => println(string) 

Wenn ich jedoch die String-Definition in den folgenden ändern, kompiliert es in beiden Fällen.

+0

Ursprünglich traf ich das Problem, während der eine Fall-Klasse machen versuchen, die einen Extraktor sein sollte auch in der Lage sein, aber wenn ich darüber nachdenke sehr viel Sinn machen tut :) – Stefan

+0

Sie keine Klasse bieten kann so wie das. 'case PersonClass =>' funktioniert nur, wenn 'PersonClass' ein Objekt ist. Um Klassen zuzuordnen, weisen Sie entweder eine lokale Variable zu: 'case e: String =>' oder entpacken, wenn es sich um ein Tuple oder eine Fallklasse handelt: '(3, 4) match {case (a, b) =>' – Ryan

Antwort

21

Der abgeleitete Typ der Zeichenfolge ist String. Das ist nach der Deklaration des Val bekannt.

Wie wir bereits bei der Mustererkennung wissen, ist es nicht sinnvoll, Muster zu vergleichen, die keine Strings sind (wie Ihre PersonClass), da sie niemals übereinstimmen. Das ist, was der "Muster-Typ ist nicht kompatibel mit erwarteten Typ; gefunden: Objekt PersonClass erforderlich: java.lang.String Fall PersonClass => println (String)" -Fehler bedeutet: Wir erwarten ein Muster, das eine Unterklasse von String ist, aber etwas gefunden (PersonClass) was nicht ist.

Wenn Sie den Typ AnyRef erzwingen, ändert sich die Situation. Der Compiler behandelt die Zeichenfolge als Anyref, sodass Muster, die AnyRef erweitern, übereinstimmen. PersonClass ist AnyRef, daher erhalten Sie keinen Fehler.

8

Wenn Sie bereits ein Objekt vom Typ String haben, wird es nie einem Typ PersonClass entsprechen. Es ist tatsächlich eine Funktion, die der Compiler nicht erlaubt, diese Übereinstimmungen auszuführen, die niemals erfolgreich sein werden.

Mit dem Typ Any schalten Sie einfach die Typprüfung aus. Es wird nicht mit dieser Definition übereinstimmen, aber der Compiler kann dieses Problem nicht finden.

5

Ich nehme an, Sie versuchen, etwas anderes zu testen, aber der Compiler ist zu schlau, um Sie zu lassen.

Vielleicht möchten Sie etwas wie folgt aus:

object Test { 
    case class Person(name: String, age: Int) { } 
    def myPrint(ar: AnyRef) { 
    ar match { 
     case s: String => println(s) 
     case Person(name, age) => println("My name is "+name) 
     case _ => println("I am a mystery!") 
    } 
    } 
    def test = { 
    myPrint("Hello, World") 
    myPrint(Person("John Doe",40)) 
    myPrint(5) 
    } 
} 

aber wie andere haben darauf hingewiesen, wenn Sie nicht tatsächlich Notwendigkeit zu tun für die anderen Typen zu überprüfen, wird der Compiler beschweren sich, dass, was du bist Tun ist sinnlos. Eine gute Sache auch: Wenn Sie keinen Test schreiben, haben Sie möglicherweise einen schwer zu debuggenden Laufzeitfehler.

0
object ws { 

case class PersonClass(name:String,age: Int) 
val p=new PersonClass("ach",25)      

    def string(x: Any) = x match { 
    case x:String => println(x) 
    case x:PersonClass => println(p.name +" "+p.age) 
    }            

    string("aa")         //> aa 
    string(p)         //> ach 25 

}