Rust Lang Book Ch.17 OOP

继承/多态性

书中认为继承给子类分享了一些可能并不需要的代码,因此并不好。Rust中最接近继承/多态的是trait。

通过使用不同的Trait和Trait bound,可以达到类似接口的效果。我们可以要求一些参数/域实现了某种Trait而无需知道究竟这些参数/域是什么具体类型,这样的参数/域称之为Trait Object。一般来说,Trait Object需要使用某些pointer,再搭配dyn关键字(即dynamically Sized type说明该trait object所占空间大小在运行时才能确定)然后再说明相关的trait。

Rust会保证传入Trait Object位置的必然已经实现了对应的Trait。

当使用Trait Object时,Rust使用dynamic dispatch,即动态分配,在运行的时候决定具体的需要使用的方法。dynamic dispatch会带来一定的运行开销,同时无法inline,或者说unrolling一些代码,但是可以带来更灵活的语法。

pub trait Draw {
    fn draw(&self);
}

pub struct Screen {
    pub components: Vec<Box<dyn Draw>>,
}

impl Screen {
    pub fn run(&self) {
        for component in self.components.iter() {
            component.draw();
        }
    }
}

pub struct Screen<T: Draw> {
    pub components: Vec<T>,
}

impl<T> Screen<T>
where
    T: Draw,
{
    pub fn run(&self) {
        for component in self.components.iter() {
            component.draw();
        }
    }
}

pub struct Button {
    pub  u32,
    pub height: u32,
    pub label: String,
}

impl Draw for Button {
    fn draw(&self) {
        // code to actually draw a button
    }
}

use gui::{Button, Screen};

fn main() {
    let screen = Screen {
        components: vec![
            Box::new(SelectBox {
                 75,
                height: 10,
                options: vec![
                    String::from("Yes"),
                    String::from("Maybe"),
                    String::from("No"),
                ],
            }),
            Box::new(Button {
                 50,
                height: 10,
                label: String::from("OK"),
            }),
//此时两种type可以混用! ], }; screen.run(); }

  

不过,这些Trait Bound所对应的Trait Object需要Object Safety,具体来说是:

1. 返回类型不能是Self。

2. 没有generic type parameters。

这些都是因为Rust使用trait object时不知道传入的trait object的具体类型,如果返回Self或者带有泛型,那就无法追踪变量类型了。

例如,带有返回Self方法clone的trait Clone就不能够使用。

pub struct Screen {
    pub components: Vec<Box<dyn Clone>>,
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` cannot be made into an object
}

  

原文地址:https://www.cnblogs.com/xuesu/p/13887974.html