2014-06-21 5 views
5

ich ToHex eine Implementierung eines Merkmals zur Verfügung stellen möchte (nicht von mir definiert, von serialize) für einen primitiven Typen u8:eine Implementierung bereitstellt, wenn beiden Züge und Typ nicht in dieser Kiste sind

impl ToHex for u8 { 
    fn to_hex(&self) -> String { 
     self.to_str_radix(16) 
    } 
} 

Das Problem werde ich diesen Compiler-Fehler:

error: cannot provide an extension implementation where both trait and type are not defined in this crate 

ich den Grund dieses Fehlers und seine Logik zu verstehen, ist dies sowohl, weil das Merkmal und die primitive Art zu meinem Code extern ist. Aber wie kann ich mit dieser Situation umgehen und eine ToHex Implementierung für u8 bereitstellen? Und allgemeiner, wie gehst du mit dieser Art von Problem um, scheint mir, dass dieses Problem üblich sein muss und es möglich und einfach sein sollte, Typen wie dieses zu erweitern?

Antwort

10

sollten Sie eine newtype Struktur verwenden, um dies zu tun:

pub struct U8(pub u8) 

impl ToHex for U8 { 
    fn to_hex(&self) -> String { 
     let U8(x) = *self; 
     x.to_str_radix(16) 
    } 
} 

Dies bedeutet jedoch, dass Sie u8 in U8 wickeln sollten, wo Sie diese Konvertierung durchführen müssen:

let x: u8 = 127u8 

// println!("{}", x.to_hex()); // does not compile 
println!("{}", U8(x).to_hex()); 

Diese ist absolut kostenlos in Bezug auf die Leistung.

+0

Es ist ein netter Hack, den Sie vorschlagen. Aber in meinem Fall mache ich mir Sorgen, dass es zu umständlich wäre, all die primitiven Typen, die ich benutze, so zu verpacken. – user3762625

+3

@ user3762625, es ist kein Hack, es ist in der Tat die einzige mögliche Methode. Sie können Merkmalsimplementierungen von Eigenschaften, die Sie nicht besitzen, nicht zu Typen hinzufügen, die Sie nicht besitzen, und es gibt keine Problemumgehung, sondern neue Typen. –

+0

@ user3762625: Nun, im vorliegenden Fall wäre es einfacher, eine "to_hex" -Freifunktion für "u8" direkt zu haben (die Sie definieren können); Sie müssen nur wirklich wickeln, wenn Sie ein "u8" übergeben müssen, wobei "ToHex" erwartet wird. –

3

Ich weiß, das ist fast ein Jahr alt, aber die Antwort wurde nie akzeptiert und ich denke, ich habe eine alternative Lösung gefunden, die ich hier gut dokumentieren wollte.

Um die Funktionalität des u8 durch Züge zu erweitern, anstatt zu versuchen, ToHex zu verlängern, warum nicht eine neue Eigenschaft erstellen?

trait MyToHex { 
    fn to_hex(&self) -> String; 
} 

impl MyToHex for u8 { 
    fn to_hex(&self) -> String { 
     format!("{:x}", *self) 
    } 
} 

verwendete dann wie so

fn main() { 
    println!("{}", (16).to_hex()); 
} 

Dies hat den Vorteil, dass Sie zu jedem u8 Variable nicht wickeln mit einem neuen und überflüssigen Datentyp.

Der Nachteil ist, dass Sie immer noch keine u8 in einer externen Funktion verwenden können (dh std Bibliothek oder eine Sie keine Kontrolle hat), die das ToHex Merkmal (Vladimir Matveev Lösung funktioniert in diesem Fall erfordert), aber von OP klingt es wie alles, was Sie tun möchten, ist u8 nur in Ihrem Code zu erweitern.

Verwandte Themen