< 返回版块

rascalrr 发表于 2022-07-06 14:22

Tags:泛型,关联类型

最近在用tokio写Framed,为适配多种不同的编解码器,用泛型包装了一下。但泛型中调用decode的返回类型是 ::Item 而非 type Item 指定的类型。 请问这里该怎么该才能把 ::Item 转换成 Message对象?

pub struct Message {}

impl Message {
    pub fn say_hi(&self) {
        println!("hi");
    }
}

pub struct Source<T> {
    _mark: std::marker::PhantomData<T>,
}

impl<T> Source<T>
where
    T: Decode + std::marker::Send,
{
    pub fn new() -> Source<T> {
        Source {
            _mark: std::marker::PhantomData::default(),
        }
    }
    pub fn run() {
        let t_entry = T::new();
        let msg = t_entry.decode().unwrap();
        msg.say_hi();  // 这里报错
        // no method named `say_hi` found for associated type `<T as Decode>::Item` in the current scope method not found in `<T as Decode>::Item`
    }
}

pub struct DecodeA {}

impl Decode for DecodeA {
    type Item = Message;

    fn decode(&self) -> Result<Self::Item, Box<dyn std::error::Error>> {
        Ok(Message {})
    }

    fn new() -> Self {
        DecodeA {}
    }
}

pub trait Decode {
    type Item;
    fn new() -> Self;
    fn decode(&self) -> Result<Self::Item, Box<dyn std::error::Error>>;
}

fn main() {
    let decodeA = DecodeA::new();
    let msg = decodeA.decode().unwrap();
    msg.say_hi();   // 这样调用是正常的

    let source: Source<DecodeA> = Source::new();
    source.run();   // 封装后就不行了
}

评论区

写评论
作者 rascalrr 2022-07-06 16:27

谢谢。 最后写在trait Decode里了,省的每个Decode都写一遍。

--
👇
Pikachu: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=ecbbf5a8ee53c36dc8bd874c5e7eb625

直接写一行就行了,没必要拆两行

where T: Decode<Item=Message> + std::marker::Send
Pikachu 2022-07-06 15:34

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=ecbbf5a8ee53c36dc8bd874c5e7eb625

直接写一行就行了,没必要拆两行

where T: Decode<Item=Message> + std::marker::Send
作者 rascalrr 2022-07-06 15:29

搞定了。在泛型的where中直接指定即可。

impl<T> Source<T>
where
    T: Decode + std::marker::Send,
    T: Decode<Item = Message>,
{
1 共 3 条评论, 1 页