Hier ist, was ich glaube passiert. Zunächst einmal S
ist den gleichen Typ überall gibt es keine Magie hier. Schauen wir uns das erste Beispiel aussehen:
scala> def cons[S <: List[Any]](t1: S, t2: S): S = if(t1.isEmpty) t1 else t2
cons: [S <: List[Any]](t1: S, t2: S)S
scala> cons(List(1), List(2.0))
res21: List[AnyVal] = List(2.0)
Wie Sie Scala richtig den nächsten gemeinsamen Vorfahren für Int
gefunden sehen und Double
, und es ist AnyVal
. In diesem Fall ist also S
AnyVal
.
lassen Sie uns dies nun versuchen:
scala> def cons[S <: List[Any]](t1: S, t2: S): S = t1 ++ t2
<console>:11: error: type mismatch;
found : List[Any]
required: S
def cons[S <: List[Any]](t1: S, t2: S): S = t1 ++ t2
^
Was ist los? Diese Fehlermeldung bedeutet, dass das Ergebnis von ++
ist irgendwie List[Any]
statt der erwarteten S
. Warum das? Lassen Sie sich bei ++
Unterschrift aussieht (vereinfachte, ist echte Unterschrift länger):
def ++[B >: A](other: List[B]): List[B] = ???
So braucht Scala die nächsten Vorfahren der A
und die tatsächlichen Typen Parameter von other
zu finden. Das einzige Problem ist: Es muss B
an dem Punkt finden, wo Sie cons
definieren, nicht wo Sie es später anwenden (B
ist kein freier Parameter für cons
). Die einzige Information ist die obere Grenze von S
, und es ist List[Any]
, so dass die einzige sichere Lösung für B
am Punkt der Definition von cons
die allgemeinste ist, d.h. Any
. Das bedeutet, dass das Ergebnis ++
ist List[Any]
, und es passt nicht S
. Daher der Fehler.
Drittes Beispiel:
scala> def cons[S <: Any](t1: List[S], t2: List[S]): List[S] = t1 ++ t2
cons: [S](t1: List[S], t2: List[S])List[S]
scala> cons(List(1), List(1.0))
res0: List[AnyVal] = List(1, 1.0)
Warum funktioniert das? Hier haben sowohl t1
als auch t2
genau den gleichen Typ, egal was S
ist (und S
kann später abgeleitet werden). So B == S
und das Ergebnis ist List[S]
. Auch in diesem speziellen Fall ist S
der nächste gemeinsame Vorfahre von Int
und Double
.
In Ihrem dritten Beispiel sagen Sie "Hier haben beide t1 und t2 genau den gleichen Typ, egal was S ist". Wie kann das sein? List [Int] List [Double] sind verschiedene Typen, nicht wahr? – Samar
Ich denke, die Verwirrung entsteht, weil verschiedene Typen anfangs als Argumente übergeben werden können, aber der Typ für S wird der nächste gemeinsame Vorfahre der verschiedenen Typen sein. – Samar
Ich zweite @ Samars Fragen. Ich sehe keinen Unterschied zwischen '(t1: S, t2: S)' und '(t1: Liste [S], t2: Liste [S])'. In beiden Fällen haben t1 und t2 genau den gleichen Typ. Natürlich können Sie 'List [Int]' und 'List [String]' übergeben, aber in diesem Fall ist der nächstliegende Vorfahre 'List [Any]', also ist das, was 'S' ist. Können Sie ein Beispiel für 'def cons [S <: Liste [Beliebige]] (t1: S, t2: S): S 'geben, wo wir einen Fehler hätten (daher lässt der Compiler das nicht zu)? Was auch immer Sie übergeben, Compiler wird schließen, dass "S" der nächste Vorfahre ist und ** das ist, was zurückgegeben wird **. Abgeleiteter Typ "S". Es sollte mit 'S' funktionieren, oder? – slouc