Rust基础-关于trait之五
基于上一篇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之五相关推荐
- Rust基础-关于trait之一
什么是trait? 答:告诉编译器类型具有哪些并且可以与其他类型共享的功能. trait是干啥的? 答:为结构抽象定义一坨共享行为.并且定义约束,用以扩展(多态). trait的规则 1.该trait ...
- 实践解析丨Rust 内置 trait:PartialEq 和 Eq
摘要:Rust 在很多地方使用了 traits, 从非常浅显的操作符重载, 到 Send, Sync 这种非常微妙的特性. 本文分享自华为云社区<Rust 内置 trait 解析:Partial ...
- 图像处理基础知识系列之五:贝叶斯方法简单梳理
图像处理基础知识系列之五:贝叶斯方法简单梳理 文章来源: 刘未鹏 数学之美番外篇:平凡而又神奇的贝叶斯方法(作者是个技术兼心理学 ...
- 从高级程序员的角度来看,Rust 基础知识
作者 | Daniel Bulant 译者 | 弯月 出品 | CSDN(ID:CSDNnews) 刚开始从事编程工作的时候,我使用的是PHP.个人感觉,PHP的语法有点笨拙且不自然,有时甚至很讨厌( ...
- Rust 基础(三)
六.枚举和模式匹配 在本章中,我们将研究enumeration,也称为enum. 枚举允许通过枚举可能的变体来定义类型. 首先,将定义和使用枚举来展示枚举如何与数据一起编码意义.接下来,将探索一个特别 ...
- Rust 基础(七)
十八.模式和匹配(Patterns and Matching) 模式是Rust中的一种特殊语法,用于匹配复杂类型和简单类型的结构.将模式与match 表达式和其他构造结合使用,可以更好地控制程序的控制 ...
- Rust基础笔记:Getting input from the console
一个例子 Rust能和其他编程语言一样从控制台获得用户输入,但Rust的处理方式确和其他语言有着很大的区别,这其中有着很多值得学习和思考的东西. 从一个小例子开始: let mut buf = Str ...
- Rust基础概念之函数
Time: 20190921 函数在Rust中是无处不在的,到现在为止,看了很多main函数,这个是程序的入口.fn表示函数声明. Rust中的编程风格是蛇形命名法,即都采用小写字母,单词之间用下划线 ...
- Rust基础概念之数据类型
Time: 20190921 数据类型概览 Rust是一种静态语言,也是一门强类型语言.每个值都对应着一个特定的类型. 编译器知道数据类型后,就知道该类型对应的确定的操作.本篇主要关注两种特定类型: ...
最新文章
- 卷积神经网络(CNN)新手指南
- activiti no processes deployed with key
- ubuntu 循环登录问题,
- [导入]做了一个页面静态化小软件,和大家分享,up有分
- layui 下拉框空选项不显示_layui下select下拉框不显示或没有效果
- 九章算法班L3 Dynamic Programming Ⅰ
- PAT乙级(1027 打印沙漏)
- C++程序设计方法3:类中的静态成员
- Python 读取/存储 yaml 文件
- 随笔-546 评论-829 文章-21 读书笔记2013第11本:《别逗了,费曼先生》
- 文件恢复原理Linux文件恢复工具-foremostextundelete
- 1024,今天给大家发100个现金红包和思否课程、掘金小册
- 再见实体店!推荐一个Python神器,能在线帮助小姐姐试衣服!
- Chrome浏览器如何清除浏览器缓存快捷键
- c 语言翻译软件,分享一款 程序员秒懂的翻译软件
- mysql 表间关联查询
- 常用串口调试工具比较(详细)
- python开发问卷系统_哪个开源的问卷调查系统最好用?
- 国产大飞机C919首飞成功 瑞星安全保驾护航
- 怎么用单片机做一个比较有创新的东西?