Rsut类型转换-From与Info

Rsut类型转换-From与Info

From与Info提供了一种显式的类型转换机制,Rust语言中不支持方法的重载和类的继承,在一些场景下可以使用From与Info达到方法重写和模拟类继承的目的。

问题描述

在GUI编程中,我们定义一个基础的Element结构体,用于描述画面上的元素,Button是Element的一个具体的实现,同时Button具有页面元素容器的功能,Button里面可以放Text和Img类型的页面元素,Text和Img都是是一种Element的具体实现, Element和Button的代码如下:

  • Element结构体定义代码
    pub struct Element{
        // ...相关属性
    }
  • Button结构体定义代码
   pub struct Button{
    content:Element,
    // ...相关属性
    }
    impl Button
    {
        pub fn new(content:Element)->Self{
            Button{
                // ...相关属性
                content
            }
        }
    }
  • Text和Img
    pub struct Img{
        // 相关属性
    }

    pub struct Text{
        // 相关属性
    }

具体实现

在Rust中是没有继承概念的,所以Img和Text是不能继承Element。Button的new方法中,接收
Element类型的参数,也不能同时接收Img或Text类型的参数。该如何解决上述问题呢?这里就可以通过From和Into的方法来实现方法的重写和类继承的关系。

这里可以通过Info和From将Text和Img转换成Element类型,Button的new方法就可以接收Text类型或Img类型的实例。在Rust中,定义的类型都默认实现了Info trait,不用显式实现Info,所以将Img和Text类型绑定到Element的From trait上。

    pub struct Img{
    // 相关属性
    }

    impl From<Img> for Element{

        fn from(img: Img) -> Self {
            Element { }
        }
    }

    pub struct Text{
        // 相关属性
    }

    impl From<Text> for Element{
        fn from(text: Text) -> Self {
            Element {  }
        }
    }

修过Button的相关定义

    pub struct Button{
        content:Element,
        // ...相关属性
    }
    impl Button
    {
        pub fn new<E>(content:E)->Self
        where E:Into<Element>
        {
            Button{
                // ...相关属性
                content:content.into()
            }
        }
    }

这样Button的new方法就可以接收Img和Text类型的参数

    let img = Img{};
    let btn = Button::new(img);

    let text = Text{};
    let btn = Button::new(text);

该方式变相的实现了方法的重载,同时让Button、Text和Img与Element有了一种层级关系,逻辑上的一种继承关系,达到组织结构体的目的。上面的代码并没有使Text、Img与Element进行关联,让Text和Img可以当一种Element进行使用,需要使用Trait Object,类似Java中的多态。

  • 1.首先定义一个trait,用于抽象Element的行为。
    trait Widget{
        fn draw(&self);
    }
  • 2.让Element拥有该行为
    pub struct Element{
        widget:Box<dyn Widget>,
        // ...相关属性
    }
    // 对行为进行包装
    impl Element{
        fn draw(&self) {
            self.widget.draw();
        }
    }
  • 3.Text和Img实现trait

    impl Widget for Img{
        fn draw(&self) {
            println!("This is img");
        }
    }
    impl Widget for Text{

        fn draw(&self) {
            println!("This is text");
        }
    }

  • 4.调整Text和Img的类型转换代码
    impl From<Img> for Element{

        fn from(img: Img) -> Self {
            Element { widget: Box::new(img) }
        }
    }

    impl From<Text> for Element{
        fn from(text: Text) -> Self {
            Element { widget: Box::new(text) }
        }
    }
  • 5、最终Button代码的实现
    pub struct Button{
        pub content:Element,
        // ...相关属性
    }
    impl Button
    {
        pub fn new<E>(content:E)->Self
        where E:Into<Element>
        {
            Button{
                // ...相关属性
                content:content.into()
            }
        }

        pub fn draw(&self){
            self.content.draw()
        }
    }

测试代码

    #[test]
    fn test_button_new(){
        let img = Img{};
        let btn = Button::new(img);
        btn.draw();

        let text = Text{};
        let btn = Button::new(text);
        btn.draw();
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 本节介绍各种常见的浏览器事件。 鼠标事件 鼠标事件指与鼠标相关的事件,主要有以下一些。 click 事件,dblc...
    许先生__阅读 2,520评论 0 4
  • 高阶函数:将函数作为参数 sortted()它还可以接收一个key函数来实现自定义的排序,reversec参数可反...
    royal_47a2阅读 709评论 0 0
  • 1. Say Hello to HTML :一级标题 :开始标签, :结束标签 2. Headline with ...
    TAsama阅读 684评论 0 1
  • jquery介绍 jQuery是目前使用最广泛的javascript函数库 据统计,全世界排名前100万的网站,有...
    就是这么帅_567e阅读 1,220评论 0 0
  • 前言:此代码,网上实例+同事提供思路+自己编码,100%手工完成,希望能认识更多的同道中人,一起探讨。 已下是简单...
    hao0_0阅读 21,107评论 4 14