Rust 中的方法(继承)和重写

Lez*_*man 2 rust

use crate::size::Size;

pub struct Car {
    pub name: String,
    pub color: (u32, u32, u32),
    pub size: Size,
    pub model: u32,
    pub private: i32,
}

impl Car {
    pub fn new() -> Self {
        Car {
            name: String::from("Default Template"),
            color: (1, 0, 1),
            size: Size::NORMAL,
            model: 2019,
            private: 2,
        }
    }
}
pub trait CommontMethods {
    fn change_name_and_model(&mut self, private: i32);
}

pub trait PrintChanges {
    fn print_changes(&self);
}

impl CommontMethods for Car {
    fn change_name_and_model(&mut self, private: i32) {
        println!("{}", self.name);
        self.model = 2000;
        self.private = private;
        self.print_changes();
    }
}

impl PrintChanges for Car {
    fn print_changes(&self) {
        println!("Model :{} , private : {}", self.model, self.private);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是Car它具有_name_and_model()调用的函数的结构print_changes()Honda具有字段的结构体car : Car {...}

调用时honda.change_name_and_model(),我希望它实际调用print_changes()本田而不是汽车中实现的函数。

use crate::car::*;
use crate::size::Size;

pub struct Honda {
    pub car: Car,
    lights_on: bool,
}

impl Honda {
    pub fn new() -> Self {
        Honda {
            car: Car {
                name: String::from("Honda"),
                color: (1, 1, 1),
                size: Size::BIG,
                model: 2002,
                private: 3,
            },
            lights_on: true,
        }
    }
}

impl PrintChanges for Honda {
    fn print_changes(&self) {
        self.car.print_changes();
        println!("this is usefull !");
    }
}
Run Code Online (Sandbox Code Playgroud)

所以当我想这样使用它时:

fn main() {
    let mut honda = Honda::new();

    honda.car.change_name_and_model(0);
}
Run Code Online (Sandbox Code Playgroud)

change_name_and_model()函数调用 的汽车实现print_changes(),但我希望它改为调用 Honda one。

这可能吗?

Tod*_*odd 5

请原谅我在这里对 OO 进行了一些重新设计。我将创建Car我的基础“类” - 或特征,HondaChevrolet从中继承。

如果您来自 Java,请将特征视为接口或抽象类。由于特征可以包含方法的默认实现,因此它们更像抽象类 - 只不过它们不能具有数据成员。

假设它Car继承了另一个特征,PrintsUpdate。这意味着HondaChevrolet必须实现它(或者如果PrintsUpdate有默认实现,则覆盖它是可选的)。

如果我们一切都做对了,我们就能得到我们想要的多态行为。例如,我们可以编写带有指向Car特征的指针并调用其方法的函数,并观察调用了正确的重写实现。

pub fn polymorphism_test()
{
    let mut honda = Honda::new("Civic", "Foolton", "Blue");
    let mut chevy = Chevrolet::new("Corvette", "Barbie", "Red");
    
    update_car(&mut honda, "Bazner", "Green");
    update_car(&mut chevy, "Quxner", "Orange");
}

pub fn update_car(car: &mut dyn Car, owner: &str, color: &str) {
    println!("Updating a {}...", car.make());
    car.update(owner, color);
}
Run Code Online (Sandbox Code Playgroud)

输出:

Updating a Honda...
Printing changes for Bazner's Green Honda Civic
Updating a Chevrolet...
Printing changes for Quxner's Orange Chevrolet Corvette
Run Code Online (Sandbox Code Playgroud)

这是我们的基本特征。我Car继承自PrintsUpdate

Updating a Honda...
Printing changes for Bazner's Green Honda Civic
Updating a Chevrolet...
Printing changes for Quxner's Orange Chevrolet Corvette
Run Code Online (Sandbox Code Playgroud)

请注意,Car::update()正在调用尚未实现的方法。这可以。Chevrolet如果他们继承,则Honda必须实施它们Car

这是我们的Honda“班级”:

pub trait Car: PrintsUpdate {
    fn make(&self) -> &str;
    fn set_owner(&mut self, name: &str);
    fn set_color(&mut self, name: &str);
    fn update(&mut self, owner: &str, color: &str)
    {
        self.set_owner(owner);
        self.set_color(color);
        self.print_changes();
    }
    //fn print_changes(&self);
}

pub trait PrintsUpdate {
    fn print_changes(&self) {
        println!("Default implementation for PrintsUpdate...");
    }
}
Run Code Online (Sandbox Code Playgroud)

Chevrolet

pub struct Honda {
    make: String,
    model: String,
    owner: String,
    color: String,
}
impl Honda {
    pub fn new(model: &str, owner: &str, color: &str) -> Self {
        Honda { 
            make : "Honda".into(), model: model.into(), 
            owner: owner.into(),   color: color.into() 
        }
    }
}

impl Car for Honda {
    fn make(&self) -> &str {
        &self.make
    }
    fn set_owner(&mut self, name: &str) {
        self.owner = name.into();
    }
    fn set_color(&mut self, color: &str) {
        self.color = color.into();
    }
}
impl PrintsUpdate for Honda {
    fn print_changes(&self) {
        println!("Printing changes for {}'s {} Honda {}", 
                 self.owner, self.color, self.model);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果Chevrolet选择不覆盖PrintsUpdate::print_changes()也没关系,因为它有一个默认实现。Chevrolet::prints_changes()如果没有注释掉的话,顶部的输出就是它的样子。下面是注释掉的。

再次运行该polymorphism_test()函数,我们得到:

Updating a Honda...
Printing changes for Bazner's Green Honda Civic
Updating a Chevrolet...
Default implementation for PrintsUpdate...
Run Code Online (Sandbox Code Playgroud)