2016-10-02 3 views
1

Wenn ich Fallklasse haben wie untenVerständnis Aufschlüsselung der Fallklassen

case class Calculator(brand: String, model: String) 
definiert

Wie es Unapply Methode Begleiter Objekt aussehen würde? Welche Art von Argumenten würde es brauchen?

Ich bin nicht in der Lage, dies zu emulieren, indem Sie eine Klasse definieren und dann ist es Companion-Objekt von mir.

class abc (age:Int, name:String) { 
} 

object abc { 
    def apply(age:Int, name:String) = new abc(age, name) 
    def unapply(obj:abc) = Some("test") 
} 

abc(1, "aaaa") 
res6: abc = [email protected] 

res6 match { 
    | case abc(1, "aaaa") => println("found") 
    | } 

error: too many patterns for object abc offering String: expected 1, found 2 
       case abc(1, "aaaa") => println("found") 
       ^
<console>:14: error: type mismatch; 
found : Int(1) 
required: String 
       case abc(1, "aaaa") => println("found") 

Antwort

2

Tzach es schlug mich ..

Ihre Fehlermeldung btw. ist wegen der Nichtübereinstimmung zwischen der Option, die Ihr unapply zurückgibt (die eine einzelne Zeichenkette enthält) und der Übereinstimmung in Ihrer case-Anweisung (mit will gegen ein Paar übereinstimmen).

Sie könnten eine NULL-Prüfung enthalten, nur um sicher zu machen (der Compiler tut, Objekte für Fallklasse Begleiter):

class Abc(val age: Int, val name: String) 

object Abc { 
    def unapply(obj: Abc): Option[(Int, String)] = 
    if (obj == null) 
     None 
    else 
     Some((obj.age, obj.name)) 
} 

Shameless Eigenwerbung: Wenn Sie in mehr Details von Pattern-Matching interessiert sind, Sie könnten meine kleine Präsentation "Everything you always wanted to know about pattern matching" nützlich finden.

3

Sie benötigen age und name Mitglieder Ihrer Klasse zu machen, so dass sie nach dem Bau zugänglich sind (kann, indem man sie val s getan werden), und sie dann in unapply verwenden:

class abc (val age:Int, val name:String) 

object abc { 
    def apply(age:Int, name:String) = new abc(age, name) 
    def unapply(candidate: abc) = Some((candidate.age, candidate.name)) 
} 

welche richtig passen würde:

scala> new abc(2, "bbbb") match { 
|  case abc(1, "aaaa") => println("found 1") 
|  case abc(2, "bbbb") => println("found 2") 
|  case _ => println("not found") 
|  } 
found 2 
2

Wenn Sie eine benutzerdefinierte Klasse erstellen möchten, die einehat 0 Verfahren und wollen die Extractor Pattern mit, es zu benutzen, the following rules should apply:

Der Rückgabetyp eines unapply gewählt werden sollte wie folgt:

  • Wenn es nur ein Test ist, eine Boolean zurück. Zum Beispiel case even()
  • Wenn es einen einzigen Unter Wert vom Typ gibt T, geben eine Option[T]
  • Wenn Sie mehrere Teilwerte T1,...,Tn, Gruppe sie in einem optionalen Tupel Option[(T1,...,Tn)] zurückkehren möchten.

Im Allgemeinen bedeutet dies für Sie, dass zB alle, die mit dem unapply Verfahren getan werden muss die dritte Option ist, die ein Tupel von Werten zurückgibt. Im Gegensatz zur Fallklasse, die automatisch unveränderbare Felder für Sie erstellt, müssen Sie Ihrer Klassendeklaration die Annotation val hinzufügen.

class abc (val age: Int, val name: String) 

Und:

def unapply(obj: abc): Option[(Int, String)] = Some((obj.age, obj.name))