如何在不同位置使用相似字段的两种类型推广函数?

时间:2017-11-17 12:26:52

标签: rust

我有一个函数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);
    }
}

要访问Moo1Moo2中的字段,我会介绍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>,但不知道该怎么做,这个问题看起来很复杂。

也许我应该使用宏来代替?

1 个答案:

答案 0 :(得分:4)

计算机科学中的任何问题都可以通过添加另一层间接来解决;当然,除了有太多这样的层之外。

因此,您错过了S特征来概括S1S2。在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的界面可用。