簡體   English   中英

隱藏兩個特征共享的關聯類型

[英]Hiding associated type shared by two traits

我具有特定消息類型的發送者和接收者的特征。

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()方法不應該要求知道消息類型(因為所有出現的消息類型都是在內部處理的),所以結構和它的方法不應該暴露消息類型。 我認為當您擁有更大的發送方-接收方網絡時,跟蹤消息類型也變得不切實際。

做這個的最好方式是什么? 我用Any 進行了嘗試,這主要是有效的。 然而,

  • 我實際上很難從Send創建一個SendAny ,對於接收者也是如此。
  • 我希望有一種更優雅和有效的方式,因為這引入了樣板和不必要的裝箱/拆箱。

這是我到目前為止所得到的:

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 然后使用特征 object, 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, S>
where
    S: Sends,
    R: Receives<Message = S::Message>,
{
    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,
    rx: R,
}

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

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

因此,該結構與消息的類型無關,但在發送方/接收方上是通用的。 還要避免Any

您也可以 go 以另一種方式使結構在消息上通用:

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>>,
    ) -> Self {
        Self{tx,rx}
    }

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

這再次避免了Any並且不需要在發送方/接收方上是通用的,但在消息類型上必須是通用的。

我不知道這兩個是否是您正在尋找的,但我沒有看到任何其他方法可以避免run需要特定類型/特征。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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