基于上一篇Rust基础-关于trait之四-不得不说一下rust fat point

如果Trait之间有继承关系时,vtable 是什么布局呢?

如果看过上一篇,那么这张图应该能够看明白了。

所有的trait这么放,那就没办法 区分fn属于哪个trait了。那么如何upcast呢?

1、upcast

通过用AsBase的trait中转一下的办法。如下代码


trait Human {fn human_say(&self) {println!("Human...");}
}
trait AsHuman {fn as_Human(&self) -> &dyn Human;
}
impl<T: Human> AsHuman for T {fn as_Human(&self) -> &dyn Human {self}
}
trait Female: AsHuman {fn human_say(&self) {println!("Female..");}
}
trait Male: AsHuman {fn human_say(&self) {println!("Male..");}
}
#[derive(Debug)]
struct Creature;
impl Female for Creature {}
impl Male for Creature {}
impl Human for Creature {}
fn main() {let s: Creature = Creature;Human::human_say(&s);Female::human_say(&s);Male::human_say(&s);let Hm: &dyn Human = s.as_Human();Hm.human_say();let f: &dyn Female = &s;f.human_say();let m:&dyn Male=&s;m.human_say();
}

输出

AsHuman这个trait完成了 Female和Male这两个trait upcast的道路。  polymorphism?yeah

2、downcast

let‘s code:

use std::any::Any;
trait Human {fn human_say(&self) {println!("Human...");}fn as_any(&self) -> &dyn Any;
}trait Female {fn human_say(&self) {println!("Female...");
}
fn as_any(&self) -> &dyn Any;
}
struct Creature;
impl Human for Creature {fn as_any(&self) -> &dyn Any {self}
}
impl Female for Creature {fn as_any(&self) -> &dyn Any {self}
}
impl Creature{fn dance(&self){println!("let dance!");}
}
fn main() {let C = Creature;let hm: &dyn Human = &C;hm.human_say();let downcast_hm = hm.as_any().downcast_ref::<Creature>().unwrap();Human::human_say(downcast_hm);Female::human_say(downcast_hm);downcast_hm.dance();
}

这段代码把hm 这个trait object再次转回Creature这个struct。Rust的Any这个trait提供这个能力。

pub trait Any: 'static {fn type_id(&self) -> TypeId;
}
//通过 type_id 就能够在运行时判断类型,不同于反射。

通过Any::type_id返回TypeId,再通过downcast_ref转回Creature这个objct。

pub fn downcast_ref<T: Any>(&self) -> Option<&T> {if self.is::<T>() {unsafe { Some(&*(self as *const dyn Any as *const T)) }} else {None}
}

在类型一致时(if self.is::<T>()),通过 unsafe 代码把 trait object 引用的第一个指针(即 data 指针)转为了指向具体类型的引用。

3、最后讲一下trait的compose

let's code:


trait Human {fn Human_say(&self) {println!("Human...");}
}
trait Boy:Human  {fn Boy_say(&self) {println!("Boy..");}
}
trait Wife  {fn Wife_say(&self) {println!("Wife..");}
}
trait Family :Boy+Wife {fn Family_say(&self) {println!("Family..");}
}
struct Creature;
impl Human for Creature {}
impl Boy for Creature {}
impl Wife for Creature {}
impl Family for Creature {}
fn Man(Tom: &dyn Family){Tom.Human_say();Tom.Boy_say();Tom.Wife_say();Tom.Family_say();
}fn main() {let s: Creature = Creature;Man(&s);
}

以上的例子,把顺序的继承关系改为平行的组合关系,相对于downcast和upcast这样的做法更清楚更易维护。但在不同的情况下各有优劣,还是要具体分析的。

相关文章

Rust基础-关于trait之一_DarcyZ_SSM的博客-CSDN博客

Rust基础-关于trait之二_DarcyZ_SSM的博客-CSDN博客

Rust基础-关于trait之三_DarcyZ_SSM的博客-CSDN博客

Rust基础-关于trait之四-不得不说一下rust fat point_DarcyZ_SSM的博客-CSDN博客

Rust基础-关于trait之六,动态派发和静态派发的区别

Rust基础-关于trait之五相关推荐

  1. Rust基础-关于trait之一

    什么是trait? 答:告诉编译器类型具有哪些并且可以与其他类型共享的功能. trait是干啥的? 答:为结构抽象定义一坨共享行为.并且定义约束,用以扩展(多态). trait的规则 1.该trait ...

  2. 实践解析丨Rust 内置 trait:PartialEq 和 Eq

    摘要:Rust 在很多地方使用了 traits, 从非常浅显的操作符重载, 到 Send, Sync 这种非常微妙的特性. 本文分享自华为云社区<Rust 内置 trait 解析:Partial ...

  3. 图像处理基础知识系列之五:贝叶斯方法简单梳理

    图像处理基础知识系列之五:贝叶斯方法简单梳理             文章来源:                  刘未鹏        数学之美番外篇:平凡而又神奇的贝叶斯方法(作者是个技术兼心理学 ...

  4. 从高级程序员的角度来看,Rust 基础知识

    作者 | Daniel Bulant 译者 | 弯月 出品 | CSDN(ID:CSDNnews) 刚开始从事编程工作的时候,我使用的是PHP.个人感觉,PHP的语法有点笨拙且不自然,有时甚至很讨厌( ...

  5. Rust 基础(三)

    六.枚举和模式匹配 在本章中,我们将研究enumeration,也称为enum. 枚举允许通过枚举可能的变体来定义类型. 首先,将定义和使用枚举来展示枚举如何与数据一起编码意义.接下来,将探索一个特别 ...

  6. Rust 基础(七)

    十八.模式和匹配(Patterns and Matching) 模式是Rust中的一种特殊语法,用于匹配复杂类型和简单类型的结构.将模式与match 表达式和其他构造结合使用,可以更好地控制程序的控制 ...

  7. Rust基础笔记:Getting input from the console

    一个例子 Rust能和其他编程语言一样从控制台获得用户输入,但Rust的处理方式确和其他语言有着很大的区别,这其中有着很多值得学习和思考的东西. 从一个小例子开始: let mut buf = Str ...

  8. Rust基础概念之函数

    Time: 20190921 函数在Rust中是无处不在的,到现在为止,看了很多main函数,这个是程序的入口.fn表示函数声明. Rust中的编程风格是蛇形命名法,即都采用小写字母,单词之间用下划线 ...

  9. Rust基础概念之数据类型

    Time: 20190921 数据类型概览 Rust是一种静态语言,也是一门强类型语言.每个值都对应着一个特定的类型. 编译器知道数据类型后,就知道该类型对应的确定的操作.本篇主要关注两种特定类型: ...

最新文章

  1. 卷积神经网络(CNN)新手指南
  2. activiti no processes deployed with key
  3. ubuntu 循环登录问题,
  4. [导入]做了一个页面静态化小软件,和大家分享,up有分
  5. layui 下拉框空选项不显示_layui下select下拉框不显示或没有效果
  6. 九章算法班L3 Dynamic Programming Ⅰ
  7. PAT乙级(1027 打印沙漏)
  8. C++程序设计方法3:类中的静态成员
  9. Python 读取/存储 yaml 文件
  10. 随笔-546 评论-829 文章-21 读书笔记2013第11本:《别逗了,费曼先生》
  11. 文件恢复原理Linux文件恢复工具-foremostextundelete
  12. 1024,今天给大家发100个现金红包和思否课程、掘金小册
  13. 再见实体店!推荐一个Python神器,能在线帮助小姐姐试衣服!
  14. Chrome浏览器如何清除浏览器缓存快捷键
  15. c 语言翻译软件,分享一款 程序员秒懂的翻译软件
  16. mysql 表间关联查询
  17. 常用串口调试工具比较(详细)
  18. python开发问卷系统_哪个开源的问卷调查系统最好用?
  19. 国产大飞机C919首飞成功 瑞星安全保驾护航
  20. 怎么用单片机做一个比较有创新的东西?

热门文章

  1. httpie实用指南
  2. 【2022最新Java面试宝典】—— SpringCloud面试题(49道含答案)
  3. 亚马逊关键词库的精细化管理分享值得你看!
  4. 自组织神经网络:Kohonen网络训练算法
  5. LabView连接Access
  6. Map集合中获取key-value值的方法
  7. Quartus II 13.0无modelsim进行仿真(用自带仿真器)
  8. 第十一章:偏最小二乘回归分析
  9. flex布局——换行——多行换行
  10. 智能家居品牌十大排名、智能洗地机品牌排行榜