Dies hat mit der Art und Weise zu tun, die Inferenz/Vereinigung in Scala funktioniert.
Wenn Sie eine Variable definieren und die Art auslassen, gilt Scala die spezifischste Art möglich:
scala> val v1 = Iterable(Array(123))
v1: Iterable[Array[Int]] = List(Array(123))
Wenn Sie jedoch den erwarteten Typen angeben (zB durch den Wert auf eine Funktion mit einem definierten vorbei Parametertyp) Scala vereint die angegebenen Parameter mit dem erwarteten Typ (wenn möglich):
scala> val v2 : Iterable[Iterable[Any]] = Iterable(Array(123))
v2: Iterable[Iterable[Any]] = List(WrappedArray(123))
Da Int
ist ein Subtyp von Any
, Vereinigung auftritt, und der Code läuft gut.
Wenn Sie möchten, dass Ihre Funktion alles akzeptiert, was ein Untertyp von Any
ist (ohne Scalas Unification-Hilfe), müssen Sie dieses Verhalten explizit definieren.
Edit:
Während das, was ich sage, teilweise wahr ist, siehe @ AlexyRomanov Antwort für eine richtige Einschätzung. Es scheint, dass die „Vereinigung“ zwischen Array
und Iterable
ist wirklich eine implizite Konvertierung genannt wird, wenn Sie Iterable(Array(123))
als Parameter (siehe die Wirkung dieses in meiner Erklärung von v2
) übergeben.
Angenommen, Sie haben ein wenig Code, wo der Compiler den Typ B
erwartet, aber stattdessen den Typ A
findet. Bevor ein Fehler ausgegeben wird, prüft der Compiler eine Sammlung impliziter Konvertierungsfunktionen auf eine mit dem Typ A => B
. Wenn der Compiler eine zufriedenstellende Konvertierung findet, wird die Konvertierung automatisch (und im Hintergrund) ausgeführt.
Der Grund f3
nicht v1
mag, ist, weil es zu spät ist eine implizite Konvertierung auf den inneren Array[Int]
und keine bestehende implizite Konvertierung für Iterable[Array[Int]] => Iterable[Iterable[Int]]
existiert zu nennen, obwohl es trivial zu implementieren wäre, wie ich weiter unten zeigen:
scala> implicit def ItAr2ItIt[T](ItAr: Iterable[Array[T]]): Iterable[Iterable[T]] = ItAr.map(_.toIterable)
ItAr2ItIt: [T](ItAr: Iterable[Array[T]])Iterable[Iterable[T]]
scala> def f3(o:Iterable[Iterable[Any]]):Unit = println("I like what I see!")
f3: (o: Iterable[Iterable[Any]])Unit
scala> val v3 = Iterable(Array(123))
v3: Iterable[Array[Int]] = List(Array(123))
scala> f3(v3)
I like what I see!
Warum 'Iterable [Alles]'? Genauso wenig wie Generika/Typ. – cchantep
Any ist die gemeinsame Schnittstelle des Objekts, das ich in meinen Sammlungen brauche. In einigen Kontexten wird Scala sauer, wenn Sie keinen Parametertyp angeben und statt dessen nichts zurückgibt, insbesondere wenn Sie Generika zurückgeben. – user48956
Vor allem, wenn Sie 'Any' benötigen, gibt es ein Designproblem – cchantep