簡體   English   中英

為特定類型實現特征方法

[英]Implementing trait methods for specific types

我正在嘗試使用兩種方法(編碼和解碼)創建 Coder 特征。 特征的每個實現只需要處理特定類型的輸入/輸出,例如:

  • BytesCoder 應該只接收 &[u8] 作為編碼輸入,並且應該只生成 &[u8] 作為解碼輸出。
  • KVCoder 應該只接收 HashMap 作為編碼輸入,並且應該只生成 HashMap 作為解碼輸出。

方法 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM