我是Rust的新手,我正在构建一个Adapter结构体,它有一个缓存来存储本地获取的数据。我已经成功地将其用于HashMap
,但我想将其泛化,让用户将其替换为任何其他实现我的Cache
Trait的类型。
如何将其重构为类似接口的实现?
pub trait Cache {
fn insert(&mut self, data: Budgets) -> anyhow::Result<()>;
}
// #[derive(Debug)]
pub struct Adapter<'a, T: Cache> {
base_uri: &'a str,
client: reqwest::blocking::Client,
default_budget: Option<&'a str>,
//cache: HashMap<String, Budget> <-- original impl
//cache: &'a dyn Cache <-- Not sure how to make this work
cache: T
}
我能够得到一个hacky解决方案,我使用上面的未注解代码,然后为我的特征创建一个新的结构:
pub struct HashCache {
cache: HashMap<String, Budget>
}
impl Cache for HashCache {
fn insert(&mut self, data: Budgets) -> anyhow::Result<()> {
for budget in data.budgets.into_iter() {
self.cache.insert(budget.name.clone(), budget);
}
Ok(())
}
}
这就要求我创建一个需要具体类型参数的脏new
方法:
impl<'a> Adapter<'a, HashCache> {
pub fn new(bearer: String) -> Self {
// -- other fields --
//cache: HashMap::new()
cache: HashCache { cache: HashMap::new() }
}
}
现在我必须遍历一个结构体,遍历该高速缓存有一个额外的问题:
pub fn show_accounts(&self, budget_name: &str) {
if let Some(b) = self.cache.cache.get(budget_name) { <-- Requires getting into the struct
if let Some(a) = &b.accounts {
println!("{:?}", a)
} else {
println!{"No accounts present"}
}
}
}
1条答案
按热度按时间dnph8jn41#
由于您在crate中定义了
Cache
,因此应该可以直接在HashMap上实现该特征:为了避免“脏的新方法”问题,您还可以要求该类型实现
Default
,因此您可以编写例如:对于
show_accounts()
,因为使用的是泛型T
,所以不应该硬编码HashMap方法,而是将这些方法添加到Cache
特征中: