使用rust 1.2.0

Problem

我仍在学习Rust(来自Javascript背景),并试图弄清楚一个struct StructB是否有可能扩展现有的struct StructA,从而使StructB拥有StructA上定义的所有字段.

在Javascript(ES6语法)中,我基本上可以这样做...

class Person {
    constructor (gender, age) {
        this.gender = gender;
        this.age = age;
    }
}
class Child extends Person {
    constructor (name, gender, age) {
        super(gender, age);
        this.name = name;
    }
}

Constraints

  • StructA来自一个我无法控制的外部cargo包.

Current Progress

我找到了这个blog post on single-inheritance,听起来正是我需要的.

但试图实现它会导致错误消息error: virtual structs have been removed from the language.后来我搜索了一下,很快就发现是implemented and then removed per RFC-341.

我也发现了这个thread about using traits,但由于StructA来自外部Cargo 包装,我认为我不可能把它变成一个特征.

那么,在铁 rust 中实现这一点的正确方法是什么呢?

推荐答案

没有任何东西能完全符合这一点.我想到了两个概念.

  1. struct 组成

    struct Person {
        age: u8,
    }
    
    struct Child {
        person: Person,
        has_toy: bool,
    }
    
    impl Person {
        fn new(age: u8) -> Self {
            Person { age: age }
        }
    
        fn age(&self) -> u8 {
            self.age
        }
    }
    
    impl Child {
        fn new(age: u8, has_toy: bool) -> Self {
            Child { person: Person::new(age), has_toy: has_toy }
        }
    
        fn age(&self) -> u8 {
            self.person.age()
        }
    }
    
    fn main() {
        let p = Person::new(42);
        let c = Child::new(7, true);
    
        println!("I am {}", p.age());
        println!("My child is {}", c.age());
    }
    

    您可以简单地将一个 struct 嵌入到另一个 struct 中.内存布局很好且紧凑,但您必须手动将所有方法从Person委派到Child,或者将一个&Person委派出go .

  2. 特点

    trait SayHi {
        fn say_hi(&self);
    }
    
    struct Person {
        age: u8,
    }
    
    struct Child {
        age: u8,
        has_toy: bool,
    }
    
    impl SayHi for Person {
        fn say_hi(&self) {
            println!("Greetings. I am {}", self.age)
        }
    }
    
    impl SayHi for Child {
        fn say_hi(&self) {
            if self.has_toy {
                println!("I'm only {}, but I have a toy!", self.age)
            } else {
                println!("I'm only {}, and I don't even have a toy!", self.age)
            }
        }
    }
    
    fn greet<T>(thing: T)
        where T: SayHi
    {
        thing.say_hi()
    }
    
    fn main() {
        let p = Person { age: 42 };
        let c = Child { age: 7, has_toy: true };
    
        greet(p);
        greet(c);
    }
    

当然,你可以把这两个概念结合起来.


As DK. mentions, you could choose to implement Deref or DerefMut. However, I do not agree that these traits should be used in this manner. My argument is akin to the argument that using classical object-oriented inheritance simply for code reuse is the wrong thing. "Favor composition over inheritance" => "favor composition over Deref". However, I do hold out hope for a language feature that enables succinct delegation, reducing the annoyance of composition.

Rust相关问答推荐

为什么函数不接受选项T参数的所有权?

如何在原始字符串中转义";#和#";

文档示例需要导入相关的 struct ,但仅在运行测试时.这是故意的行为吗?

告诉Rust编译器返回值不包含构造函数中提供的引用

有没有可能让泛型Rust T总是堆分配的?

允许 rust 迹 struct 条目具有多种类型

正在将带有盒的异步特征迁移到新的异步_fn_in_特征功能

使用 Option 来分配?

Nom 解析器无法消耗无效输入

一次不能多次borrow *obj作为可变对象

我可以用 Rust 编写一个不可变变量

在描述棋盘时如何最好地使用特征与枚举

trait 对象指针的生命周期

为什么带有生命周期指定的方法不能被调用两次?

为什么数组不像向量那样在 for 块之后移动?

我的 Axum 处理程序无法编译:未实现 IntoResponse 特征

当 `T` 没有实现 `Debug` 时替代 `unwrap()`

Abortable:悬而未决的期货?

Rust:如果我知道只有一个实例,那么将可变borrow 转换为指针并返回(以安抚borrow 判断器)是否安全?

如果返回类型是通用的,我可以返回 &str 输入的一部分吗?