我正在编写一个命令行任务管理应用程序来自学 Rust。
到目前为止,我有一个 sqllite 和一个内存数据源。
pub struct TaskManager {
source: Datasource, // here rustc complains
}
经理引用了
Datasource
,这是一个特征:
pub trait Datasource {
type Settings;
fn start(&self) -> Result<bool>;
}
Main 读取 cli 参数并根据它们决定应实例化哪些数据源。
但是,Rust 告诉我
”- rustc: 中关联类型
的值Settings
必须指定 [E0191]”source::Datasource
我知道类型必须在编译时指定,并且到目前为止两个源都指定了类型。
impl Datasource for SqlLiteDataSource {
type Settings = SqlLiteSettings;
}
impl Datasource for MemoryDataSource {
type Settings = MemorySettings;
}
在解析 cli args 时,会评估所有分支:
pub fn new(datasource: Datasources) -> Self {
let ds: Datasource = match datasource {
Datasources::SqlLite { path } => SqlLiteDataSource::new(path.to_string()),
_ => MemoryDataSource::new(),
};
}
事实上 rustc 也在这里抱怨同样的错误。
我们的想法是每个具体实现都有自己的设置。然后,我如何将通用特征变量分配给
TaskManager
,以便后端根据提供的源完成任务管理?
问题是你不能将具有类型的特征直接放入结构中。您需要在 TaskManager 内部使用 Boxed 特征,因为 Rust 编译器需要知道数据源的特定类型(在本例中为 Settings)。更改行
source: Datasource
以使用默认设置类型或另一个盒装特征定义盒装特征。如果您有特定的默认设置类型,则可以将其设置为进行编译,只需将行更改为 source: Box<dyn Datasource<Settings=ChosenType>>
或者您也可以使用行 source: Box<dyn Datasource<Settings=Box<dyn Settings>>>
将设置设置为盒装特征
这将向 Rust 编译器阐明 TaskManager 结构内部 Datasource 特征的指定类型。