rust - 隐藏两个特征共享的关联类型
问题描述
我具有特定消息类型的发送者和接收者的特征。
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
这主要是有效的。然而,
- 我实际上很难
SendAny
从 a中创建 aSend
,并且对于接收器也是如此。 - 我希望有一种更优雅和有效的方式,因为这引入了样板和不必要的装箱/拆箱。
这是我到目前为止所得到的:
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());
}
}
解决方案
您应该在此处创建将Sends
and绑定Receives
在一起的类型SendAndReceiveInner
。然后使用 trait 对象,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 表示取决于读者。
推荐阅读
- php - 从数据库到数组到字符串
- python - 在 django 中使用 indpectdb 创建所有表模型
- vb.net - 如何在 vb.net httprequest 中使用 newtonsoft.json.linq.serializeobject 转换 \?
- ionic-framework - 如何在 Ionic 3 的离子幻灯片中将标题放在图像中间?
- react-native - 销毁 React Native Webview
- razor - 从 cshtml 页面向控制器发送日期值
- java - 如何在 WSO2 IoT Server 3.3.0 中添加会话超时
- c# - 为什么热量导致我的 Windows 服务无法添加到 Windows 注册表/Windows 服务中
- react-native - React Native 如何获取当前月份的第一个和最后一个日期到 DatePicker
- javascript - 在 UWP Javascript 应用程序中的两个窗口之间共享状态或传递消息