特征的继承

在 Rust 中,没有继承结构属性的概念。相反,当你设计对象之间的关系时,请通过接口( Rust 中的特征 ) 定义一个人的功能。这促进了组合而不是继承 ,这被认为更有用,更容易扩展到更大的项目。

这是在 Python 中使用一些示例继承的示例:

class Animal:
    def speak(self):
        print("The " + self.animal_type + " said " + self.noise)

class Dog(Animal):
    def __init__(self):
        self.animal_type = 'dog'
        self.noise = 'woof'

为了将其转化为 Rust,我们需要取出构成动物的内容并将该功能纳入特征。

trait Speaks {
     fn speak(&self);

     fn noise(&self) -> &str;
}

trait Animal {
    fn animal_type(&self) -> &str;
}

struct Dog {}

impl Animal for Dog {
    fn animal_type(&self) -> &str {
        "dog"
    }
}  

impl Speaks for Dog {
    fn speak(&self) {
        println!("The dog said {}", self.noise());
    }

    fn noise(&self) -> &str {
        "woof"
    }
}

fn main() {
    let dog = Dog {};
    dog.speak();
}

请注意我们如何将该抽象父类拆分为两个独立的组件:将结构定义为动物的部分以及允许它发声的部分。

精明的读者会注意到这并不是一对一的,因为每个实施者都必须重新实现逻辑,以“The {animal} say {noise}”的形式打印出一个字符串。你可以通过稍微重新设计我们为 Animal 实现 Speak 的界面来做到这一点:

trait Speaks {
     fn speak(&self);
}

trait Animal {
    fn animal_type(&self) -> &str;
    fn noise(&self) -> &str;
}

impl<T> Speaks for T where T: Animal {
    fn speak(&self) {
        println!("The {} said {}", self.animal_type(), self.noise());
    }
}

struct Dog {}
struct Cat {}

impl Animal for Dog {
    fn animal_type(&self) -> &str {
        "dog"
    }
    
    fn noise(&self) -> &str {
        "woof"
    }
}

impl Animal for Cat {
    fn animal_type(&self) -> &str {
        "cat"
    }

    fn noise(&self) -> &str {
        "meow"
    }
}

fn main() {
    let dog = Dog {};
    let cat = Cat {};
    dog.speak();
    cat.speak();
}

现在请注意,动物会产生噪音并简单地说现在已经实现了任何动物。这比以前的方式和 Python 继承更灵活。例如,如果你想添加一个具有不同声音的 Human,我们可以改为使用 speak 的另一个实现 Human

trait Human {
    fn name(&self) -> &str;
    fn sentence(&self) -> &str;
}

struct Person {}

impl<T> Speaks for T where T: Human {
    fn speak(&self) {
        println!("{} said {}", self.name(), self.sentence());
    }
}