我有一个函数algo
,它适用于S1
类型,我也有
类型S2
,其中包含S1
的所有字段以及一些其他字段。
如何修改algo
以同时接受S2
作为输入
创建类型为S1
的临时变量和来自S2
的数据?
struct Moo1 {
f1: String,
f2: i32,
}
struct Moo2 {
f1: String,
f2: i32,
other_fields: f32,
}
struct S1 {
x: i32,
v: Vec<Moo1>,
}
struct S2 {
x: i32,
v: Vec<Moo2>,
}
//before fn algo(s: &S1)
fn algo<???>(???) {
//work with x and v (only with f1 and f2)
}
我被困的地方
我们假设algo
有这个实现(我的实际应用程序有另一个实现):
fn algo(s: &S1) {
println!("s.x: {}", s.x);
for y in &s.v {
println!("{} {}", y.f1, y.f2);
}
}
要访问Moo1
和Moo2
中的字段,我会介绍trait AsMoo
,并访问x
字段和v
我会介绍trait AsS
:
trait AsMoo {
fn f1(&self) -> &str;
fn f2(&self) -> i32;
}
trait AsS {
fn x(&self) -> i32;
// fn v(&self) -> ???;
}
fn algo<S: AsS>(s: &AsS) {
println!("s.x: {}", s.x());
}
我坚持执行AsS::v
方法。我没有分配内存来使用我的algo
,但我需要以某种方式Vec<&AsMoo>
。
也许我需要返回某种Iterator<&AsMoo>
,但不知道该怎么做,这个问题看起来很复杂。
也许我应该使用宏来代替?
答案 0 :(得分:4)
计算机科学中的任何问题都可以通过添加另一层间接来解决;当然,除了有太多这样的层之外。
因此,您错过了S
特征来概括S1
和S2
。在S
中,您可以使用名为关联类型的功能:
trait Moo {
fn f1(&self) -> &str;
fn f2(&self) -> i32;
}
trait S {
type Mooer: Moo;
fn x(&self) -> i32;
fn v(&self) -> &[Self::Mooer];
}
位type Mooer: Moo;
说:我不太清楚Mooer
的确切类型最终会是什么,但它会实现Moo
特征。< / p>
这可以让你写:
impl S for S1 {
type Mooer = Moo1;
fn x(&self) -> i32 { self.x }
fn v(&self) -> &[Self::Mooer] { &self.v }
}
impl S for S2 {
type Mooer = Moo2;
fn x(&self) -> i32 { self.x }
fn v(&self) -> &[Self::Mooer] { &self.v }
}
fn algo<T: S>(s: &T) {
println!("s.x: {}", s.x());
for y in s.v() {
println!("{} {}", y.f1(), y.f2());
}
}
您的通用algo
知道无论Mooer
类型最终是什么类型,它都符合Moo
特征,因此Moo
的界面可用。