2016-12-14 1 views
2

Ich habe eine Eigenschaft, die eine Schnittstelle für Objekte definiert, die einen Wert enthalten können. Der Zug hat einen Weg, um den aktuellen Wert des Erhaltens:Wie abstrahiere ich über einen Verweis auf einen Wert oder einen Wert selbst?

pub trait HasValue<T> { 
    fn get_current_value(&self) -> &T; 
} 

Das ist in Ordnung, aber ich erkennen, dass in Abhängigkeit von der tatsächlichen Implementierung, manchmal ist es zweckmäßig, einen Verweis zurück, wenn T in einem Feld gespeichert wird, und es ist manchmal bequem, um einen Klon von T zurückzugeben, wenn das Hintergrundfeld über Threads geteilt wurde (zum Beispiel). Ich habe Mühe herauszufinden, wie ich dies in der Eigenschaft darstellen soll. Ich könnte so etwas wie dieses:

pub enum BorrowedOrOwned<'a, T: 'a> { 
    Borrowed(&'a T), 
    Owned(T) 
} 

impl<'a, T: 'a> Deref for BorrowedOrOwned<'a, T> { 
    type Target = T; 

    fn deref(&self) -> &T { 
     use self::BorrowedOrOwned::*; 

     match self { 
      &Borrowed(b) => b, 
      &Owned(ref o) => o, 
     } 
    } 
} 

Und get_current_value() ändern, um eine BorrowedOrOwned<T> zurückzukehren, aber ich bin nicht sicher, dass diese idiomatischen ist. BorrowedOrOwned<T> Art erinnert mich an Cow<T>, aber da der Punkt Cow ist copy-on-write und ich werde alle Schreibvorgänge verwerfen, das scheint semantisch falsch.

Ist Cow<T> der richtige Weg, um eine Referenz oder einen eigenen Wert zu abstrahieren? Gibt es einen besseren Weg als BorrowedOrOwned<T>?

+0

Würde einen zugeordneten Typ 'B: Borrow ' Arbeit zurückgeben? –

+0

@ChrisEmerson Ich bin nicht sicher, was die Kompromisse dabei tun würde, also bin ich mir nicht sicher. Könnten Sie das ein wenig erweitern? Dies scheint eine Frage zu sein, die allgemein nützlich sein kann, so dass ich an allen Antworten interessiert bin, auch wenn sie nicht auf meine spezifische Situation eingehen. –

+0

Ich denke, eigentlich hilft es nicht direkt; Du brauchst immer noch etwas wie "Kuh". –

Antwort

7

Ich schlage vor, Sie verwenden eine Cow, da Ihre BorrowedOrOwned hat keinen Unterschied zu Cow mit der Ausnahme, dass es weniger Komfort Methoden hat. Jeder, der ein BorrowedOrOwned Objekt ergreift, könnte darauf passen und den eigenen Wert oder eine veränderbare Referenz darauf erhalten. Wenn Sie die Verwirrung vermeiden wollen, eine veränderbare Referenz oder das Objekt selbst erhalten zu können, gilt auch die folgende Lösung.

Für Ihren Anwendungsfall würde ich einfach bei &T bleiben, da es keinen Grund gibt, die API komplexer zu machen. Wenn ein Benutzer eine usize wünscht, wenn Tusize ist, können sie die Referenz einfach dereferenzieren.

Ein eigenes Objekt macht nur Sinn, wenn Sie erwarten, dass der Benutzer es tatsächlich in einer eigenen Art und Weise verarbeitet. Und selbst dann ist Cow dazu gedacht, über große/schwere Objekte zu abstrahieren, die Sie an dem Besitzer übergeben, um niemanden an clone zu binden. Ihr Anwendungsfall ist das Gegenteil, Sie möchten kleine Objekte nach Besitz übergeben, um zu verhindern, dass Benutzer kleine Objekte kopieren müssen, und stattdessen kopieren Sie sie.

+0

Danke für den Rat. Bei der Vereinfachung des Problems habe ich meine Gründe falsch angegeben, weil ich manchmal ein "& T" zurückgeben wollte und manchmal ein "T" zurückgeben musste. Wenn die Implementierung "T" in einem "Arc >" (zum Beispiel) speichert, ist es nicht möglich, einfach ein "& T" zurückzugeben. 'T' muss geklont werden, und da der Klon auf dem Stack der Funktion lebt, kann kein Verweis darauf zurückgegeben werden. Ich hoffe, das ist hilfreich. PS. Es war toll mit dir bei RBR zu reden :) –

+1

Ah! Das macht mehr Sinn. Nun .. Ich schlage dann vor, dass Ihre "BorrowedOrOwned" sollte "enum Borrow <'a, T> {Ref (& 'a T), Arc (Arc >), Rc (Rc >)}' oder etwas in dieser Richtung sein.Es ist kompliziert durch die "RefCell", da viele Anwendungsfälle keine "RefCell" drin haben wollen, aber ohne mehr über den Anwendungsfall zu wissen, würde ich vermuten, dass es das Problem lösen würde. –

+0

Sehr wahr. Ich werde etwas damit herumspielen müssen, aber ich werde dies als die Antwort bezeichnen, da du meine Frage zu Kuh beantwortet hast und das hat mich definitiv in die richtige Richtung gelenkt. Danke –

Verwandte Themen