我正在编写一个命令行任务管理应用程序来自学 Rust。
到目前为止,我有一个 sqllite 和一个内存数据源。
pub struct TaskManager {
source: Datasource, // here rustc complains
}
经理对 有一个引用Datasource
,这是一个特征:
pub trait Datasource {
type Settings;
fn start(&self) -> Result<bool>;
}
Main 读取 cli args 并根据它们决定应该实例化哪个数据源。
然而 Rust 告诉我
“- rustc:必须指定关联类型的值 [E0191
Settings
] ”source::Datasource
我理解必须在编译时指定类型,并且到目前为止两个源都已指定其类型。
impl Datasource for SqlLiteDataSource {
type Settings = SqlLiteSettings;
}
impl Datasource for MemoryDataSource {
type Settings = MemorySettings;
}
并且在解析 cli 参数时,将评估所有分支:
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
以使用默认 Settings 类型或另一个装箱特征定义 Boxed 特征。如果您有特定的默认 Settings 类型,您可以将其设置为编译,您只需将该行更改为,source: Box<dyn Datasource<Settings=ChosenType>>
或者您也可以使用以下行将 Settings 设置为装箱特征source: Box<dyn Datasource<Settings=Box<dyn Settings>>>
这将向 Rust 编译器阐明 TaskManager 结构内的 Datasource 特征的指定类型。