Ich benutze Scala schon eine Weile und dachte, ich würde wirklich anfangen alles zu verstehen (naja, die meisten Dinge ...), aber ich fand mich durch eine Reihe von Methodendefinitionen in der Map-Klasse verwirrt. Ich weiß, wie foldLeft usw. funktioniert, aber was mich verwirrt, sind die Typparameter, die in den Kartenfunktionen benutzt werden. Lassen Sie uns foldLeft als Beispiel verwenden:Was sind die Regeln für den Fall, dass die Parameter des Trait/Class-Typs Vorrang vor den Parametern des Methodentyps haben?
foldLeft [B] (z: B)(op: (B, (A, B)) ⇒ B) : B
die Definition für den Map trait selbst nimmt zwei 'A' Typ-Parameter und 'B' (z Map [A + B]). Wenn ich einen Typparameter für eine Methode definiere, die denselben Namen wie einen der Typparameter für die Klasse/das Merkmal verwendet, überschreibt dies den Klassen-/Merkmalswert. Nehmen Sie diese Definition von Foo als Beispiel:
class Foo[A : Manifest, B : Manifest] {
def isAString() = manifest[A] == manifest[String]
def isAInt() = manifest[A] == manifest[Int]
def isBString() = manifest[B] == manifest[String]
def isBInt() = manifest[B] == manifest[Int]
def nowIsBString[B : Manifest] = manifest[B] == manifest[String]
}
scala> val f = new Foo[String,Int]
f: Foo[String,Int] = [email protected]
scala> f.isAString
res290: Boolean = true
scala> f.isAInt
res291: Boolean = false
scala> f.isBString
res292: Boolean = false
scala> f.isBInt
res293: Boolean = true
scala> f.nowIsBString[String]
res294: Boolean = true
scala> f.nowIsBString[Int]
res295: Boolean = false
So in der foldLeft Definition, 'B' stammt aus der Methodendefinition und 'A' kommt aus dem Zug Definition. Zum Beispiel:
val xm = Map("test" -> 1, "test2" -> 2)
scala> val foldFn = (z: Int, kv: (String, Int)) => z + kv._2
foldFn: (Int, (String, Int)) => Int = <function2>
scala> m.foldLeft(0)(foldFn)
res298: Int = 3
Dies wird als als ‚B‘ für die Funktion Streichhölzer ‚B‘ für das Merkmal erwartet, aber was ist, wenn ich den Typ, B 'für die Funktion String statt Int ändern:
scala> val foldFn = (z: String, kv: (String, String)) => z + kv._2
foldFn: (String, (String, String)) => java.lang.String = <function2>
scala> m.foldLeft("")(foldFn)
<console>:19: error: type mismatch;
found : (String, (String, String)) => java.lang.String
required: (java.lang.String, (java.lang.String, Int)) => java.lang.String
m.foldLeft("")(foldFn)
sie also die kv-Parameter (String, Int) ändern:
scala> val foldFn = (z: String, kv: (String, Int)) => z + kv._2
foldFn: (String, (String, Int)) => java.lang.String = <function2>
scala> m.foldLeft("")(foldFn)
res299: java.lang.String = 12
im Gegensatz zu meinem Foo Beispiel, in diesem Fall die die Karte 'B' Wert wird Vorrang vor den Funktionen Definition nehmen, aber nur für der kv-Parameter. Was hätte ich erwartet, ist eine foldLeft definiert, um zu sehen, wie folgt:
foldLeft[C] (z: C)(op: (C, (A, B)) => C): C
, dass mehr für mich klar sein würde, aber es ist nicht diese Art und Weise definiert. Kennt also jemand die Regeln dafür, wann ein Methodenparameter einen Trait/Class-Parameter überschreibt und wann nicht?
Aus irgendeinem Grund scheint ich nur die Antwort auf meine Frage zu finden, nachdem ich posten :) http://StackOverflow.com/Questions/8397684/Type-Parameter-of-Minbybf-ab-BImplicit-cmp-Orderingb-ab Allerdings würde ich gerne wissen, ob es Regeln gibt, um herauszufinden, wann dies passiert ist. – Mike
'foldLeft' ist definiert auf' TraversableOnce'. Es ist 'A' Parameter ist der' TraversableOnce', nicht der von 'Map'. –