我有两种方法可以做非常相似的事情,我想使用泛型和特征边界来重构。
以下是我的示例中的两种工作方法。
fn some_method_a(some_arg: u8) -> (Mode, Vec<A>)
{
let mode = match some_arg {
0 => Mode::ZERO,
_ => Mode::NOTZERO,
};
let some_as = vec![A::new(0), A::new(1)];
(mode, some_as)
}
fn some_method_b(some_arg: u8) -> (Mode, Vec<B>)
{
let mode = match some_arg {
0 => Mode::ZERO,
_ => Mode::NOTZERO,
};
let some_bs = vec![B::new("Testing".to_string())];
(mode, some_bs)
}
这是应该取代两者的方法。
fn some_method<T>(some_arg: u8) -> (Mode, Vec<T>)
where
T: Filterable,
{
let mode = match some_arg {
0 => Mode::ZERO,
_ => Mode::NOTZERO,
};
match &mode {
&Mode::ZERO => (mode, vec![A::new(0), A::new(1)]),
_ => (mode, vec![B::new("Testing".to_string())]),
}
}
但是,我现在收到此错误,即使A(和B)实现了Filterable特征,我已将其指定为该方法的特征绑定。
error[E0308]: mismatched types
--> src/main.rs:11:36
|
11 | &Mode::ZERO => (mode, vec![A::new(0), A::new(1)]),
| ^^^^^^^^^ expected type parameter, found struct `A`
|
= note: expected type `T`
found type `A`
Permalink to playground 这是该计划的其余部分:
#[derive(Debug)]
enum Mode {
ZERO,
NOTZERO,
}
trait Filterable {
fn get_some_data(&self) -> u8 {
0
}
}
struct A {
some_data: u8,
}
struct B {
some_other_data: String,
}
impl A {
fn new(some_data: u8) -> A {
A { some_data }
}
}
impl B {
fn new(some_other_data: String) -> B {
B { some_other_data }
}
}
impl Filterable for A {
fn get_some_data(&self) -> u8 {
self.some_data
}
}
impl Filterable for B {}
some_method需要做什么才能返回模式元组和A或B结构的向量?
答案 0 :(得分:1)
我对Rust泛型的理解是它们更像是C ++模板而不是你可能习惯的,因为它们在编译时是单态的并且是扩展的。
基本上是这样做的:
fn some_method<T>(some_arg: u8) -> (Mode, Vec<T>)
where T: Filterable,
...是(如果编译成功)创建此方法的两个版本。期望返回(Mode, Vec<A>)
的人和期望返回(Mode, Vec<B>)
的人。当你以这种方式思考时,这根本没有意义。
你想要的是返回实现特征Filterable
的东西的向量。因此,由于特征是未定义的,因此需要将它们包含在具有已知大小的某事中。 Box
&#39}}可以解决这个问题:
fn some_method(some_arg: u8) -> (Mode, Vec<Box<Filterable>>)
这完全取消了泛型,只是返回一个盒装Filterable
的矢量 - 实现实例。
当然,方法体现在也必须成为这个:
match &mode {
&Mode::ZERO => (mode, vec![Box::new(A::new(0)), Box::new(A::new(1))]),
_ => (mode, vec![Box::new(B::new("Testing".to_string()))]),
}
导致代码编译。