隐藏由两个特征共享的关联类型

问题描述

我有特定消息类型的发送者和接收者的特征。

pub trait Sends {
    type Message;
    fn send(&self) -> Self::Message;
}

pub trait Receives {
    type Message;
    fn receive(&mut self,msg: Self::Message);
}

我希望能够使用传递消息的 run() 方法(即 receiver.receive(sender.send()))将一对兼容的发送方和接收方存储在结构中。

我的直觉是这个 run() 方法不应该需要消息类型的知识(因为所有出现的消息类型都是在内部处理的),因此结构及其方法不应该公开消息类型。我认为,当您拥有更大的发送方-接收方网络时,跟踪消息类型也变得不切实际。

这样做的最佳方法是什么?我 tried it outAny,这主要是有效的。然而,

  • 我实际上很难从 SendAny 创建 Send,对于接收器也是如此。
  • 我希望有一种更优雅、更有效的方法,因为这引入了样板文件和不必要的装箱/拆箱。

这是我目前得到的:

trait SendsAny {
    fn send_any(&self) -> Box<dyn Any>;
}

impl<T> SendsAny for T
where
    T: Sends,T::Message: 'static,{
    fn send_any(&self) -> Box<dyn Any> {
        Box::new(self.send())
    }
}

// Similar for ReceivesAny

struct SendAndReceive {
    // These have to have matching Message types
    tx: Box<dyn SendsAny>,rx: Box<dyn ReceivesAny>,}

impl SendAndReceive {
    fn new<M: 'static>(
        tx: Box<dyn Sends<Message = M>>,rx: Box<dyn Receives<Message = M>>,) -> Self {
        // This doesn't work
        let tx = tx as Box<dyn SendsAny>;
        todo!()
    }

    fn run(&mut self) {
        self.rx.receive_any(self.tx.send_any());
    }
}

解决方法

您应该创建将 SendsReceives 绑定在一起的类型,此处为 SendAndReceiveInner。然后使用特征对象 Box<dyn SendAndReceiveAny>SendAndReceive 中以类型擦除形式使用它。

struct SendAndReceiveInner<R,S>
where
    S: Sends,R: Receives<Message = S::Message>,{
    tx: S,rx: R,}

trait SendAndReceiveAny {
    fn run(&mut self);
}

impl<R,S> SendAndReceiveAny for SendAndReceiveInner<R,{
    fn run(&mut self) {
        self.rx.receive(self.tx.send());
    }
}

struct SendAndReceive {
    inner: Box<dyn SendAndReceiveAny>,}

impl SendAndReceive {
    fn new<R,S>(tx: S,rx: R) -> Self
    where
        S: Sends + 'static,R: Receives<Message = S::Message> + 'static,{
        Self {
            inner: Box::new(SendAndReceiveInner{ tx,rx }),}
    }

    fn run(&mut self) {
        self.inner.run();
    }
}

这涉及的拳击少得多,但仍然有点样板。您可以只在 Box<dyn ...> 形式中使用它,因为此时最外层的 SendAndReceive 并没有做太多事情,但封装和 API 呈现取决于读者。

,

我不太清楚这是否是您要查找的内容,但您可以使发送方和接收方的 SendAndReceive 通用:

pub trait Sends {
    type Message;
    fn send(&self) -> Self::Message;
}

pub trait Receives {
    type Message;
    fn receive(&mut self,msg: Self::Message);
}

struct SendAndReceive<R,S> 
    where S: Sends,R: Receives<Message=S::Message>
{
    // These have to have matching Message types
    tx: S,}

impl<R,S> SendAndReceive<R,R: Receives<Message=S::Message>
{
    fn new(tx: S,) -> Self {
        Self{tx,rx}
    }

    fn run(&mut self) {
        self.rx.receive(self.tx.send());
    }
}

因此该结构与消息的类型无关,但在发送方/接收方上是通用的。还要避免整个 Any 机器。

您也可以采用另一种方式,使消息中的结构通用:

pub trait Sends {
    type Message;
    fn send(&self) -> Self::Message;
}

pub trait Receives {
    type Message;
    fn receive(&mut self,msg: Self::Message);
}

struct SendAndReceive<M> {
    // These have to have matching Message types
    tx: Box<dyn Sends<Message=M>>,rx: Box<dyn Receives<Message=M>>,}

impl<M> SendAndReceive<M> {
    fn new(
        tx: Box<dyn Sends<Message = M>>,rx: Box<dyn Receives<Message = M>>,rx}
    }

    fn run(&mut self) {
        self.rx.receive(self.tx.send());
    }
}

这再次避免了 Any 并且不需要在发送方/接收方上通用,但必须在消息类型上通用。

我不知道这两个是否是您要查找的内容,但我没有看到任何其他方法可以避免 run 需要特定类型/特征。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...