特征的继承
在 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());
}
}