Vererbt in algebraischen Datentypen

8

Ich habe Probleme, die Regeln für Merkmale in algebraischen Datentypen zu verstehen. Hier ist ein vereinfachtes Beispiel:

%Vor%

Das obige kann nicht kompiliert werden, die folgende Fehlermeldung wird ausgegeben:

%Vor%

Warum ist pond.push(duck) gültig, aber lake.push(mallard) nicht? In beiden Fällen wurde ein Duck geliefert, wo ein Quack erwartet wurde. In der ersten ist der Compiler glücklich, aber in der zweiten ist es nicht.

Liegt der Grund für diesen Unterschied in CoerceUnsized ?

    
rlkw1024 05.06.2015, 02:31
quelle

2 Antworten

6

Das ist ein korrektes Verhalten, auch wenn es etwas unglücklich ist.

Im ersten Fall haben wir folgendes:

%Vor%

Beachten Sie, dass push() , wenn Vec<Box<Quack>> aufgerufen wird, Box<Quack> akzeptiert und Sie Box<Duck> übergeben. Das ist in Ordnung - rustc kann nachvollziehen, dass Sie einen Boxed-Wert in ein Trait-Objekt wie hier konvertieren möchten:

%Vor%

Im zweiten Fall haben wir das:

%Vor%

Hier akzeptiert push() Rc<RefCell<Box<Quack>>> , während Sie Rc<RefCell<Box<Duck>>> :

bereitstellen %Vor%

Und jetzt gibt es Ärger. Box<T> ist ein DST-kompatibler Typ und kann daher als Container für ein Merkmalsobjekt verwendet werden. Das gleiche gilt bald auch für Rc und andere intelligente Zeiger, wenn Dieser RFC ist implementiert. In diesem Fall gibt es jedoch keinen Zwang von einem konkreten Typ zu einem Merkmalsobjekt, da sich Box<Duck> innerhalb von zusätzlichen Typenschichten befindet ( Rc<RefCell<..>> ).

Denken Sie daran, dass das Merkmalobjekt ein Fettzeiger ist, also unterscheidet sich Box<Duck> von Box<Quack> in der Größe. Folglich sind sie im Prinzip nicht direkt kompatibel: Sie können nicht einfach Bytes von Box<Duck> nehmen und sie dorthin schreiben, wo Box<Quack> erwartet wird. Rust führt eine spezielle Konvertierung durch, dh es ruft einen Zeiger auf die virtuelle Tabelle für Duck ab, erstellt einen Fettzeiger und schreibt ihn in Box<Quack> -typisierte Variable.

Wenn Sie Rc<RefCell<Box<Duck>>> haben, müsste rustc jedoch wissen, wie Sie sowohl RefCell als auch Rc konstruieren und destrukturieren, um dieselbe Fettzeigerkonvertierung auf seine Interna anzuwenden. Da dies Bibliothekstypen sind, kann es natürlich nicht wissen, wie es geht. Dies gilt auch für jeden anderen Wrappertyp, z. Arc oder Mutex oder sogar Vec . Sie erwarten nicht, dass Vec<Box<Duck>> als Vec<Box<Quack>> verwendet werden könnte, oder?

Es gibt auch eine Tatsache, dass in dem Beispiel mit Rc die aus Box<Duck> und Box<Quack> erstellten Rcs nicht verbunden worden wären - sie hätten unterschiedliche Referenzzähler gehabt.

Das bedeutet, dass eine Umwandlung von einem konkreten Typ in ein Merkmalsobjekt nur stattfinden kann, wenn Sie direkten Zugriff auf einen Smart-Zeiger haben, der DST unterstützt, nicht wenn er in einer anderen Struktur verborgen ist.

Das heißt, ich sehe, wie es möglich ist dies für einige ausgewählte Typen zu ermöglichen. Zum Beispiel könnten wir eine Art von Construct / Unwrap Merkmalen einführen, die dem Compiler bekannt sind und die es verwenden könnten, innerhalb eines Stapels von Wrappern zu "erreichen" und darin die Umwandlung von Objekteigenschaften durchzuführen. Allerdings hat noch niemand dieses Ding entworfen und einen RFC darüber zur Verfügung gestellt - wahrscheinlich, weil es kein weit verbreitetes Feature ist.

    
Vladimir Matveev 05.06.2015, 07:14
quelle
1

Vladimirs Antwort erklärte, was Compiler tut. Basierend auf diesen Informationen entwickelte ich eine Lösung: Erstellen eines Wrappers struct um Box<Quack> .

Der Wrapper heißt QuackWrap . Es hat eine feste Größe, und es kann wie jeder andere verwendet werden andere Struktur (denke ich). Die Box in% QuackWrap erlaubt mir ein QuackWrap zu erstellen um irgendein Merkmal, das Quack implementiert. So kann ich ein Vec<Rc<RefCell<QuackWrap>>> haben wobei die inneren Werte eine Mischung aus Duck s, Goose s usw. sind.

%Vor%

Als zusätzlichen Komfort möchte ich wahrscheinlich Deref und DefrefMut implementieren %Code%. Aber das ist für das obige Beispiel nicht notwendig.

    
rlkw1024 05.06.2015 17:35
quelle

Tags und Links