gpt4 book ai didi

rust - 在继承自另一个特征的特征中指定关联类型

转载 作者:行者123 更新时间:2023-11-29 07:59:21 25 4
gpt4 key购买 nike

我开始着手我的第一个更雄心勃勃的 Rust 项目,并努力解决我在用于学习的任何资源和教程中都没有遇到的问题。问题的标题捕获了抽象问题,但对于示例,我将使用我正在与之抗争的具体示例。

对于我的项目,我需要与不同的第三方服务接口(interface),我决定使用 actix框架作为我领域中不同参与者的抽象。该框架定义了 Actor必须实现的特征:

use actix::prelude::*;

struct MyActor {
count: usize,
}

impl Actor for MyActor {
type Context = Context<Self>;
}

我有自己的特点,它定义了第三方集成的接口(interface)。我们称它为Client .我希望每个客户都像 Actor 一样行事。

use actix::Actor;

pub trait Client: Actor {}

我在其他地方有一个向量,它存储对系统中所有事件客户端的引用。当我编译代码时,出现以下错误:

error[E0191]: the value of the associated type `Context` (from the trait `actix::actor::Actor`) must be specified
--> transponder/src/transponder.rs:15:26
|
15 | clients: Vec<Box<Client>>
| ^^^^^^ missing associated type `Context` value

我现在花了几个小时试图解决这个问题,但没有一个奏效。

  • 我试图在特征中指定类型,但得到了 associated type defaults are unstable作为一个错误。
  • 我试图在特征的实现中指定类型(impl Simulation),但得到的是associated types are not allowed in inherent impls作为一个错误。
  • 我用 impl <T: Actor> Simulation for T 尝试了一些东西(例如 here 所示),但没有任何效果。

我的假设是我缺少关于特征和类型的重要知识。如果有人能帮助我解决我的问题,并指出我丢失的拼图的方向,我将不胜感激。我觉得这里有一个关于 Rust 的重要类(class),我真的很想学习。

最佳答案

只要我从您的代码中了解到,您的主要目标是将所有客户端/Actor 添加到一个集合中,并在需要时调用它的常见行为。但是由于对象安全性,这是不可能的,所以我们可以通过一些技巧来实现(创建模仿客户端的特征,我将其命名为 ClientProxy)。

I have a trait of my own that defines the interface for the third-party integrations. Let's call it Client. I want each client to behave like an actor.

pub trait Client: Actor {}

是的,它是这样工作的,实际上这意味着如果某个结构有 Client 的实现,它也需要有 Actor 的实现。

考虑我们有两个上下文 MyActorOtherActor 以及它们的 Client/Actor 实现。我们在客户端中有一个行为( behave_like_client(&self) )。

pub trait Client: Actor {
fn behave_like_a_client(&self);
}

struct MyActor {
count: usize,
}

impl Actor for MyActor {
type Context = Context<Self>;
}
impl Client for MyActor {
fn behave_like_client(&self) {
println!("I am MyActor as Client, and my count is {}", self.count);
}
}

struct OtherActor {
count: usize,
}

impl Actor for OtherActor {
type Context = Context<Self>;
}
impl Client for OtherActor {
fn behave_like_client(&self) {
println!("I am OtherActor Client, and my count is {}", self.count);
}
}

现在我们有了用于测试的 Actors,但让我们回到对象安全问题,我们无法将这些客户端收集到一个集合中。这就是为什么我创建了 ClientProxy 来模仿 Client 并且我想在 Clients 上实现 ClientProxy。我们可以通过在扩展客户端的泛型上实现 ClientProxy 来做到这一点:

//ClientProxy must have all behaviors in Client 
trait ClientProxy {
fn behave_like_client(&self);
}

//This code implements ClientProxy to all Client like Objects
impl<T> ClientProxy for T
where
T: Client,
{
fn behave_like_client(&self) {
self.behave_like_client();
}
}

现在一切就绪,我们可以测试我们的结构了:

struct Container {
clients: Vec<Box<ClientProxy>>,
}

fn main() {
let mut container = Container {
clients: Vec::new(),
};
let a = Box::new(MyActor { count: 3 });
let b = Box::new(OtherActor { count: 4 });

container.clients.push(a);
container.clients.push(b);

container
.clients
.iter()
.for_each(|a| a.behave_like_client());
//output :
//I am MyActor as Client, and my count is 3
//I am OtherActor Client, and my count is 4
}

您可以从 playground 获得完整代码(由于缺乏依赖性,它没有在 Playground 上运行)

关于rust - 在继承自另一个特征的特征中指定关联类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53805212/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com