特徵的繼承

在 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());
    }
}