kovariante Typ A tritt in kontravarianter Position im Typ A des Wertes a auf

8

Ich habe folgende Klasse:

%Vor%

Und der Compiler klagen:

%Vor%

Ich habe viel nach dem Fehler gesucht, konnte aber nichts Nützliches finden hilf mir den Fehler zu verstehen.

Könnte jemand bitte erklären, warum der Fehler auftritt?

    
zero_coding 03.04.2017, 08:53
quelle

4 Antworten

15

Die Fehlermeldung ist wirklich sehr klar, sobald Sie es verstehen. Lass uns zusammen kommen.

Sie deklarieren die Klasse Box als Kovariante in ihrem Typparameter A . Dies bedeutet, dass für jeden Typ X extinguing A (d. H.% Co_de%), X <: A als Box[X] betrachtet werden kann.

Um ein klares Beispiel zu geben, betrachten wir den Box[A] -Typ:

%Vor%

Wenn Sie Animal und Dog <: Animal definieren, können sowohl Cat <: Animal als auch Box[Dog] als Box[Cat] betrachtet werden, und Sie können z. Erstellen Sie eine einzelne Sammlung, die beide Typen enthält, und bewahren Sie den Typ Box[Animal] auf.

Obwohl diese Eigenschaft in einigen Fällen sehr nützlich sein kann, werden auch die Operationen eingeschränkt, die Sie für Box[Animal] bereitstellen können. Aus diesem Grund können Sie im Compiler Box nicht definieren.

Wenn Sie die Definition von

erlauben %Vor%

dann ist der folgende Code gültig:

%Vor%

Die letzte Zeile ist offensichtlich ein Problem, weil def set jetzt ein catBox enthält! Die Argumente einer Methode erscheinen in der sogenannten kontravarianten Position, die das Gegenteil der Kovarianz ist. Wenn Sie Dog definieren, dann bedeutet Box[-A] Cat <: Animal ( Box[Cat] >: Box[Animal] ist ein Supertyp von Box[Cat] ). Für unser Beispiel ist das natürlich unsensibel.

Eine Lösung für Ihr Problem besteht darin, die Box[Animal] -Klasse unveränderlich zu machen (dh keine Möglichkeit zu geben, den Inhalt von Box zu ändern) und stattdessen die in Ihrem Box -Begleiter definierte apply-Methode zu erstellen neue Boxen. Wenn Sie möchten, können Sie case class auch lokal definieren und nicht irgendwo außerhalb von set angeben, indem Sie es als Box deklarieren. Der Compiler wird dies erlauben, weil private[this] garantiert, dass die letzte Zeile unseres fehlerhaften Beispiels nicht kompiliert wird, da die Methode private[this] außerhalb einer bestimmten Instanz von set vollständig unsichtbar ist.

    
francoisr 03.04.2017, 09:12
quelle
8

Andere haben bereits eine Antwort gegeben, warum der Code nicht kompiliert wird, aber sie haben keine Lösung für die Kompilierung des Codes angegeben:

%Vor%

Das Typargument B >: A ist eine untere Grenze, die den Compiler anweist, bei Bedarf einen Supertyp abzuleiten. Wie im Beispiel zu sehen ist, wird Animal abgeleitet, wenn Cat angegeben wird.

    
sschaef 03.04.2017 14:10
quelle
1

Versuchen Sie zu verstehen, was es für Ihre Box[+A] bedeutet, in A :

kovariant zu sein

Dies bedeutet, dass ein Box[Dog] auch ein Box[Animal] sein sollte, also sollte jede Instanz von Box[Dog] alle Methoden haben, die ein Box[Animal] hat.

Insbesondere sollte eine Box[Dog] eine Methode

haben %Vor%

Es hat jedoch nur eine Methode

%Vor%

Nun könntest du denken, dass du die erste von der zweiten ableiten kannst, aber das ist nicht der Fall: Ich möchte eine Cat mit nur der zweiten Signatur einkisten? Das ist nicht machbar, und das sagt Ihnen der Compiler: Ein Parameter in einer Methode ist eine kontravariante Position (Sie können nur kontravariante (oder invariante) Typparameter eingeben).

    
Cyrille Corpet 03.04.2017 09:04
quelle
1

Im Grunde können Sie A s nicht setzen, wenn A kovariant ist, Sie können es nur herausnehmen (zB: A zurückgeben). Wenn Sie A s eingeben möchten, müssen Sie contravariant angeben.

%Vor%

Möchten Sie beides tun, dann machen Sie es einfach invariant

%Vor%

Das Beste ist, es kovariant zu halten und den Setter loszuwerden und einen unveränderlichen Ansatz zu wählen.

    
Sleiman Jneidi 03.04.2017 08:59
quelle

Tags und Links