[英]Hiding associated type shared by two traits
I have traits for senders and receivers of a specific message type.我具有特定消息类型的发送者和接收者的特征。
pub trait Sends {
type Message;
fn send(&self) -> Self::Message;
}
pub trait Receives {
type Message;
fn receive(&mut self, msg: Self::Message);
}
I want to be able to store a compatible pair of sender and receiver in a struct with a run()
method that passes messages, ie receiver.receive(sender.send())
.我希望能够使用传递消息的
run()
方法将一对兼容的发送方和接收方存储在一个结构中,即receiver.receive(sender.send())
。
My intuition is that this run()
method should not require knowledge of the message type (because all occurrences of the message type are handled internally), so the struct and its method should not expose the message type.我的直觉是这个
run()
方法不应该要求知道消息类型(因为所有出现的消息类型都是在内部处理的),所以结构和它的方法不应该暴露消息类型。 I think keeping track of the message types also becomes impractical when you have a bigger sender-receiver network.我认为当您拥有更大的发送方-接收方网络时,跟踪消息类型也变得不切实际。
What is the best way to do this?做这个的最好方式是什么? I tried it out with
Any
, which mostly works.我用
Any
进行了尝试,这主要是有效的。 However,然而,
SendAny
from a Send
, and same for the receiver.Send
创建一个SendAny
,对于接收者也是如此。 Here is what I've got so far:这是我到目前为止所得到的:
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());
}
}
You should make the type that binds the Sends
and Receives
together, here SendAndReceiveInner
.您应该创建将
Sends
和Receives
绑定在一起的类型,这里SendAndReceiveInner
。 And then use a trait object, Box<dyn SendAndReceiveAny>
to use it in the type-erased form in SendAndReceive
.然后使用特征 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();
}
}
This has a lot less boxing involved but still a bit of boilerplate.这涉及的拳击要少得多,但仍然有点样板。 You could just use it in the
Box<dyn...>
form since the outermost SendAndReceive
isn't doing much at this point, but encapsulation and API presentation is up to the reader.您可以只在
Box<dyn...>
表单中使用它,因为此时最外面的SendAndReceive
并没有做太多事情,但封装和 API 演示文稿取决于读者。
I don't quite know if this is what you are looking for, but you could make the SendAndReceive
generic on the sender and receiver:我不太清楚这是否是您正在寻找的,但您可以在发送者和接收者上使
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());
}
}
The struct is therefore agnostic to the type of the message but generic on the sender/receiver.因此,该结构与消息的类型无关,但在发送方/接收方上是通用的。 Also avoid the whole
Any
machinery.还要避免
Any
。
You could also go the other way and make the struct generic on the message:您也可以 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());
}
}
This again avoids Any
and doesn't need to be generic on the sender/receiver but must be generic on the message type.这再次避免了
Any
并且不需要在发送方/接收方上是通用的,但在消息类型上必须是通用的。
I don't know whether these two are what you are looking for, but I don't see any other way to avoid run
needing specific types/traits.我不知道这两个是否是您正在寻找的,但我没有看到任何其他方法可以避免
run
需要特定类型/特征。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.