![](/img/trans.png)
[英]How can I implement the From trait for all types implementing a trait but use a specific implementation for certain types?
[英]Implementing trait methods for specific types
我正在尝试使用两种方法(编码和解码)创建 Coder 特征。 特征的每个实现只需要处理特定类型的输入/输出,例如:
方法 1:满足编译器的一种简单方法是让编码和解码接受 Any,并让每个实现分别处理它。 这似乎是个坏主意,因为每个编码员应该只处理一种类型。
type SomeEncodableHopefully = Box<dyn std::any::Any>;
pub trait Coder {
fn encode(&self, element: SomeEncodableHopefully) -> &[u8];
fn decode(&self, bytes: &[u8]) -> SomeEncodableHopefully;
}
pub struct BytesCoder {
...
}
impl BytesCoder {
pub fn new() -> Self {
...
}
}
impl Coder for BytesCoder {]
// "element" should only be &[u8] instead of Any
fn encode(&self, element: SomeEncodableHopefully) -> &[u8] {
...
}
// The output shouldn't be Any either
fn decode(&self, bytes: &[u8]) -> SomeEncodableHopefully {
...
}
}
pub struct KVCoder {
...
}
impl KVCoder {
pub fn new() -> Self {
...
}
}
impl Coder for KVCoder {]
// "element" should only be HashMap<...> instead of Any
fn encode(&self, element: SomeEncodableHopefully) -> &[u8] {
...
}
// The output shouldn't be Any either
fn decode(&self, bytes: &[u8]) -> SomeEncodableHopefully {
...
}
}
fn test_coder(coder: Box<dyn Coder>, to_encode: SomeEncodableHopefully, to_decode: &[u8]) {
let encoded:&[u8] = coder.encode(to_encode);
let decoded:SomeEncodableHopefully = coder.decode(to_decode);
}
方法 2:我尝试使用关联类型,但无法为 Coder 的每个实现成功定义固定类型:
pub trait Coder {
// The compiler ignores Element on each implementation and requires
// this to be defined manually when a coder is used
type Element;
fn encode(&self, element: Self::Element) -> &[u8];
fn decode(&self, bytes: &[u8]) -> Self::Element;
}
...
impl Coder for BytesCoder {
// This gets ignored
type Element = &[u8];
fn encode(&self, element: Self::Element) -> &[u8] {
...
}
fn decode(&self, bytes: &[u8]) -> Self::Element {
...
}
}
...
// Error on coder: the value of the associated type `Element` (from trait `Coder`) must be specified
fn test_coder(coder: Box<dyn Coder>, to_encode: SomeEncodableHopefully, to_decode: &[u8]) {
let encoded:&[u8] = coder.encode(to_encode);
let decoded:SomeEncodableHopefully = coder.decode(to_decode);
}
方法 3:定义特定类型的编码和解码版本可能是个好主意。 我没有收到编译器的投诉,但如果涉及许多类型(包括,例如:HashMap<A,B>、HashMap<A,C>,...),这将非常冗长:
pub trait Coder {
fn encode_to_bytes(&self, element: &[u8]) -> &[u8] {
panic!("Invalid operation for this type of coder");
}
fn decode_to_bytes(&self, bytes: &[u8]) -> &[u8] {
panic!("Invalid operation for this type of coder");
}
fn encode_to_some_other_type (&self, element: SomeOtherType) -> &[u8] {
panic!("Invalid operation for this type of coder");
}
fn decode_to_some_other_type (&self, bytes: &[u8]) -> SomeOtherType {
panic!("Invalid operation for this type of coder");
}
}
...
// Ok
impl Coder for BytesCoder {
fn encode_to_bytes(&self, element: &[u8]) -> &[u8] {
...
}
fn decode_to_bytes(&self, bytes: &[u8]) -> &[u8] {
...
}
}
...
第三种方法似乎有点体面地解决了问题,但是有没有更好的方法来实现这一点?
第二种方法的错误要求您指定Coder
的类型,它必须与to_encode
的类型匹配才能工作。 我在这里引入一个泛型,以使其尽可能灵活。
fn test_coder<E>(coder: Box<dyn Coder<Element = E>>, to_encode: E, to_decode: &[u8]) {
let encoded: &[u8] = coder.encode(to_encode);
let decoded: E = coder.decode(to_decode);
}
这留下了 SirDarius 提出的谁拥有您的切片的问题。 您可能应该返回一个拥有的类型,因为通常您不能从每种类型中获取&[u8]
:
pub trait Coder {
type Element;
fn encode(&self, element: Self::Element) -> Vec<u8>;
fn decode(&self, bytes: &[u8]) -> Self::Element;
}
struct BytesCoder;
type SomeEncodableHopefully = Vec<u8>;
impl Coder for BytesCoder {
type Element = Vec<u8>;
fn encode(&self, element: Self::Element) -> Vec<u8> {
element
}
fn decode(&self, bytes: &[u8]) -> Self::Element {
bytes.to_vec()
}
}
如果Element
必须是引用,您可以使用 GAT 代替。 或者让这个特质持续一生。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.