如何重用结构体的通用代码?

Mad*_*Lee 3 rust

我想重用结构代码。例如:

use std::fmt::Display;

struct CommonStruct<T: Display> {
    // could have more fields
    data: T
}

struct A<T: Display> {
    com: CommonStruct<T>,
    age: i32
}

struct B<T: Display> {
    com: CommonStruct<T>,
    name: String
}

impl<T: Display> A<T> {
    // could be more common functions
    fn print_data(&self) {
        // could be more complicated
        println!("data: {}", self.com.data);
    }
}

impl<T: Display> B<T> {
    // could be more common functions
    fn print_data(&self) {
        // could be more complicated
        println!("data: {}", self.com.data);
    }
}

fn main() {
    let a = A{ com: CommonStruct{data: 10}, age: 0 };
    a.print_data();
    let b = B{ com: CommonStruct{data: 12}, name: "123".to_string() };
    b.print_data();
}
Run Code Online (Sandbox Code Playgroud)

其中AB具有一些由CommonStruct和 一些常见函数封装的公共字段(例如,print_data)。

我尝试使用trait但无法找出解决方案:

use std::fmt::Display;

struct CommonStruct<T: Display> {
    // could have more fields
    data: T
}

struct A<T: Display> {
    com: CommonStruct<T>,
    age: i32
}

struct B<T: Display> {
    com: CommonStruct<T>,
    name: String
}

trait Common {
    // could be more common functions
    fn print_data(&self) {
        print_data(&self)
    }
}

impl<T: Display> Common for A<T> {
}

impl<T: Display> Common for B<T> {
}

fn print_data(t: &Common) {
    // could be more complicated
    println!("data: {}", t.com.data);
}

fn main() {
    let a = A{ com: CommonStruct{data: 10}, age: 0 };
    a.print_data();
    let b = B{ com: CommonStruct{data: 12}, name: "123".to_string() };
    b.print_data();
}
Run Code Online (Sandbox Code Playgroud)

Sch*_*ern 5

由于print_data只使用了CommonStruct,并且A和B不共享其他字段,因此将其作为CommonStruct的实现并直接调用它。

impl <T: Display> CommonStruct<T> {
    fn print_data(&self) {
        println!("data: {}", self.data);
    }
}

fn main() {
    let a = A{ com: CommonStruct{data: 10}, age: 0 };
    a.com.print_data();
    let b = B{ com: CommonStruct{data: 12}, name: "123".to_string() };
    b.com.print_data();
}
Run Code Online (Sandbox Code Playgroud)

或者,创建一个具有具体实现的特征,print_data该特征依赖于获取数据的方法。

trait HasData<T: Display> {
    fn get_data(&self) -> &T;
    fn print_data(&self) {
        // could be more complicated
        println!("data: {}", self.get_data());
    }
}
Run Code Online (Sandbox Code Playgroud)

那么每个人只需要实现如何获取数据即可。

impl<T: Display> HasData<T> for CommonStruct<T> {
    fn get_data(&self) -> &T {
        return &self.data;
    }
}

impl<T: Display> HasData<T> for A<T> {
    fn get_data(&self) -> &T {
        return &self.com.data;
    }
}

impl<T: Display> HasData<T> for B<T> {
    fn get_data(&self) -> &T {
        return &self.com.data;
    }
}

fn main() {
    let a = A{ com: CommonStruct{data: 1}, age: 0 };
    a.print_data();
    let b = B{ com: CommonStruct{data: 2}, name: "123".to_string() };
    b.print_data();
    let c = CommonStruct{data: 3};
    c.print_data();
}
Run Code Online (Sandbox Code Playgroud)

  • @HaoLi你的数据结构非常抽象,这使得很难提出好的建议。对于您实际面临的任何问题,很可能都有更好的解决方案。 (2认同)