我正在尝试定义两个可以在以后通过多种方式实现的特征。
第一个是 trait A
,第二个是 trait B
,它基本上是一个实现 trait A
的元素向量。
trait A {
fn name(&self) -> &str;
}
trait B {
fn len(&self) -> usize;
fn add<T: A>(&mut self, item: T) -> bool;
}
#[derive(PartialEq)]
struct ImplA {
name: String,
}
impl A for ImplA {
fn name(&self) -> &str {
&self.name
}
}
struct ImplB {
items: Vec<ImplA>,
}
impl B for ImplB {
fn len(&self) -> usize {
self.items.len()
}
fn add(&mut self, item: ImplA) -> bool {
if !self.items.contains(&item) {
self.items.push(item);
true
} else {
false
}
}
}
add
函数的代码强制项实现类型 A。
然后我定义了两个结构体 ImplA
来实现 trait A
没有问题
然后结构 ImplB
应该实现 trait B
但只接受
输入 ImplA
。
我为 add
函数的签名尝试了几种组合,但没有成功编译。
原来的错误是
error[E0308]: mismatched types
--> src/main.rs:32:33
|
31 | fn add<T: A>(&mut self, item: T) -> bool {
| ----- this type parameter
32 | if !self.items.contains(&item) {
| ^^^^^ expected struct `ImplA`, found type parameter `ImplA`
|
= note: expected reference `&ImplA` (struct `ImplA`)
found reference `&T` (type parameter `T`)
我想我明白,但提到的解决方案并没有解决我的问题,因为它意味着 ImplB
可以接受任何实现 A
的结构,这不是我想要的。
答案 0 :(得分:2)
您遇到的一个问题是 add()
的类型参数在每次调用时都允许 A
的不同实现,但在其他地方您依赖它总是相同的类型对于 B
的给定实现。
在 Rust 中,可以使用 B
trait 上的关联类型来表达此约束:
trait B {
type Item: A;
fn len(&self) -> usize;
fn add(&mut self, item: Self::Item) -> bool;
}
然后,当您实现 B
时,您为该实现提供了 A
的固定类型:
impl B for ImplB {
type Item = ImplA;
fn len(&self) -> usize {
self.items.len()
}
fn add(&mut self, item: ImplA) -> bool {
if !self.items.contains(&item) {
self.items.push(item);
true
} else {
false
}
}
}