• 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
    }
    

      

  • 相关阅读:
    20145209刘一阳《JAVA程序设计》课堂测试总结
    20145209刘一阳《JAVA程序设计》第一周课堂测试
    20145209刘一阳《JAVA程序设计》第十五周补充测试
    20145209刘一阳《JAVA程序设计》第九周课堂测试
    20145209刘一阳《JAVA程序设计》第八周课堂测试
    20145209刘一阳《JAVA程序设计》第七周课堂测试
    20145209刘一阳《JAVA程序设计》第五周课堂测试
    20145209刘一阳《JAVA程序设计》第四周课堂测试
    20145209刘一阳《JAVA程序设计》第三周课堂测试
    2019-2020-2 20175322周弋鸿 《网络对抗技术》Exp9 Web安全基础
  • 原文地址:https://www.cnblogs.com/xuesu/p/13887974.html
Copyright © 2020-2023  润新知