zoukankan      html  css  js  c++  java
  • 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
    }
    

      

  • 相关阅读:
    类的有参方法
    WPF 中的设备无关单位
    Skelta BPM.NET 2006 初探
    Reporting Services Handscript
    C语言I博客作业03
    C语言I博客作业02
    C++类的运算符重载和转换函数结合的问题
    C++ 函数返回类成员的问题
    kaggle 利用linear regression 进行房价预测
    android Could not open: c:\。。。。\.android/avd/XXXX.ini 问题和解决方法
  • 原文地址:https://www.cnblogs.com/xuesu/p/13887974.html
Copyright © 2011-2022 走看看