我有两个Actix演员。 MyActor1
定义了其字段之一实现的通用特征。 MyActor2
不需要定义T
,而且我不知道如何从MyActor1::from_registry()
消息处理程序调用{{1}},而无需知道MyActor2
映射到什么类型
我尝试了这种变化:
T
这是行不通的,因为除非在let addr: Addr<MyActor1<T>> = MyActor1::from_registry();
上定义了T
,然后将其添加到struct MyActor2<T: Thing>
,否则我不知道在何处/如何定义impl<T> Handler<Msg> for MyActor2<T> where T:...
。
我也尝试过此操作,但由于Thing
未实现Default
(因为这是一个特质)而无法使用:
let addr: Addr<MyActor1<Thing>> = MyActor1::from_registry();
这是我正在使用的示例:
Cargo.toml
[package]
name = "actix-example"
version = "0.1.0"
authors = ["me"]
edition = "2018"
[dependencies]
actix = "0.8.1"
main.rs
#![allow(dead_code)]
use actix::prelude::*;
trait Thing {
fn name(&self) {}
}
#[derive(Default)]
struct One;
impl Thing for One {}
#[derive(Default)]
struct Two;
impl Thing for Two {}
// MyActor1
#[derive(Default)]
struct MyActor1<T: Thing> {
thing: T,
}
impl<T> Actor for MyActor1<T>
where
T: Thing + 'static + Default,
{
type Context = Context<Self>;
}
impl<T> Supervised for MyActor1<T> where T: Thing + 'static + Default {}
impl<T> SystemService for MyActor1<T> where T: Thing + 'static + Default {}
impl<T> Handler<Msg> for MyActor1<T>
where
T: Thing + 'static + Default,
{
type Result = ();
fn handle(&mut self, _msg: Msg, _ctx: &mut Context<Self>) {}
}
// MyActor2
#[derive(Default)]
struct MyActor2;
#[derive(Message)]
struct Msg;
impl Actor for MyActor2 {
type Context = Context<Self>;
}
impl Supervised for MyActor2 {}
impl SystemService for MyActor2 {}
impl Handler<Msg> for MyActor2 {
type Result = ();
fn handle(&mut self, _msg: Msg, _ctx: &mut Context<Self>) {
let addr = MyActor1::from_registry();
}
}
fn main() {
let sys = System::new("test");
let act1 = MyActor1 {
thing: One::default(),
};
let act2 = MyActor2::default();
actix::SystemRegistry::set(act1.start());
actix::SystemRegistry::set(act2.start());
let _ = sys.run();
}
运行代码时,出现此错误:
error[E0283]: type annotations required: cannot resolve `_: Thing`
--> src/main.rs:50:20
|
50 | let addr = MyActor1::from_registry();
| ^^^^^^^^^^^^^^^^^^^^^^^
|
note: required by `MyActor1`
--> src/main.rs:15:1
|
15 | struct MyActor1<T: Thing> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
我知道这可以解决此示例:
let addr: Addr<MyActor1<One>> = MyActor1::from_registry();
如果我在运行时不知道MyActor1<T>
是什么,该怎么办?例如,也许我有一些代码可以在运行时根据命令行参数将MyActor1
初始化为MyActor1<Two>
。
答案 0 :(得分:1)
TL; DR:MyActor1
不是一种类型,而是一种蓝图。
当您声明struct Foo<T>
时,Foo
不是类型,这是编译器创建类型的蓝图,或者,正如计算机科学所希望的那样,它是类型构造函数 >。
如果有房子的设计图,则无法打开设计图的门并在卧室里小睡:没有卧室,一旦房子建成,就可以知道卧室的外观
这里同样适用。您不能在需要 type 的地方使用 type构造函数。
您将获得3种解决方案:
MyActor1
设为类型,删除参数T
;例如,它可以将T
存储为Box<Thing>
。MyActor2
为通用名称,并添加参数T
。哪种情况下最好的解决方案在很大程度上取决于您的用例,因此我不愿意根据简化的示例给出任何建议。