Rust 多态
Rust 多态
分发
多态的上下文中的方法解析过程被称为分发,调用该方法称为分发化,在支持多态的主流语言中,分发可以通过以下任意一种方式进行。
静态分发
当在编译期决定要调用的方法时,它被称为静态分发或早期绑定。
Rust中的泛型属于静态分发,因为即使泛型函数可以接收多种类型参数,但是在编译时会生成特定类型的专用副本。
动态分发
直到运行时才能确定调用的方法,被称为动态分发。这是因为具体类型被隐藏,只能通过接口实例调用。
在动态分发过程中,可以通过对vtable(虚表)接口的实现列表进行查找,并调用该方法来动态确定相关方法。vtable是一个在固定偏移处为每个对象的方法保留一个函数指针的结构体。
特征对象(trait object)
特征对象是Rust执行动态分发的方式,它被实现为胖指针,并且是不定长类型,这意味着它们只能在引用符号(&)后面使用。特征对象胖指针具有指向与对象关联的实际数据的第一指针和指向vtable的第二指针。在运行时,我们没有实际类型的具体信息,只能通过trait的信息在vtable中找到适当的方法并调用。
trait object实现多态:
use std::fmt::Debug;
#[derive(Debug)]
struct Square(f32);
#[derive(Debug)]
struct Rectangle(f32,f32);
trait Area:Debug {
fn get_area(&self)->f32;
}
impl Area for Square {
fn get_area(&self)->f32 {
self.0*self.0
}
}
impl Area for Rectangle {
fn get_area(&self)->f32 {
self.0*self.1
}
}
fn main() {
let s:&dyn Area=&Square(3f32);
println!("{:?}",s.get_area());
let rec:&dyn Area=&Rectangle(4f32,2f32);
println!("{:?}",rec.get_area());
}
特征对象的一个用例是在一个集合中存储多种不同类型但具有共同trait的实例:
use std::fmt::Debug;
#[derive(Debug)]
struct Square(f32);
#[derive(Debug)]
struct Rectangle(f32,f32);
trait Area:Debug {
fn get_area(&self)->f32;
}
impl Area for Square {
fn get_area(&self)->f32 {
self.0*self.0
}
}
impl Area for Rectangle {
fn get_area(&self)->f32 {
self.0*self.1
}
}
fn main() {
let shapes:Vec<&dyn Area>=vec![&Square(3f32),&Rectangle(4f32,2f32)];
for e in shapes{
println!("{:?}",e.get_area());
}
}
注意:上述实例将Square和Rectangle的构造为特征对象,由于我们不知道实际类型的大小,所以dyn Trait是一个不定长类型,只能作为引用使用。或者将其置于特征其他智能指针之后:
let s:Box<dyn Area>=Box::new(Square(3f32));
println!("{:?}",s.get_area());
let rec:Box<dyn Area>=Box::new(Rectangle(4f32,2f32));
println!("{:?}",rec.get_area());
let shapes:Vec<Box<dyn Area>>=vec![Box::new(Square(3f32)),Box::new(Rectangle(4f32,2f32))];
for e in shapes{
println!("{:?}",e.get_area());
}
还可以将dyn Trait作为函数参数,以接收不同实际类型的实例参数:
fn get_area(item:&dyn Area)->f32{
item.get_area()
}
fn main() {
let shapes:Vec<&dyn Area>=vec![&Square(3f32),&Rectangle(4f32,2f32)];
for e in shapes{
println!("{:?}",get_area(e));
}
}
Rust 多态的更多相关文章
- Rust 智能指针(一)
Rust 智能指针(一) 1.Box<T> Box<T>是指向堆中的指针. fn main() { let box = Box::new(3); println!(" ...
- Rust 中的类型转换
1. as 运算符 as 运算符有点像 C 中的强制类型转换,区别在于,它只能用于原始类型(i32 .i64 .f32 . f64 . u8 . u32 . char 等类型),并且它是安全的. 例 ...
- rust语法
目录 rust语法 前言 一.数据类型 1.1 标量scalar 1.2 复合compound 1.3 切片slice 1.4 引用(借用)reference 1.5 智能指针smart pointe ...
- Rust学习笔记一 数据类型
写在前面 我也不是什么特别厉害的大牛,学历也很低,只是对一些新语言比较感兴趣,接触过的语言不算多也不算少,大部分也都浅尝辄止,所以理解上可能会有一些偏差. 自学了Java.Kotlin.Python. ...
- the rust book 的简单入门笔记
rust learning day 1 (2021/05/27) 学了常量,变量,数据类型,控制流,所有权 char 的宽度是4字节,一个 unicode 的宽度 控制流条件都不要括号 rust 中的 ...
- rust漫游 - 写时拷贝 Cow<'_, B>
rust漫游 - 写时拷贝 Cow<'_, B> Cow 是一个写时复制功能的智能指针,在数据需要修改或者所有权发生变化时使用,多用于读多写少的场景. pub enum Cow<'a ...
- Rust极简教程
目录 简介 特性 特征 用途 安装 核心组件 常用命令 基础语法 数据类型 标量类型 复合类型 示例 条件语句 循环 输出&输入 输出 输出花括号 输出非基础类型 输入 所有权 切片 结构体 ...
- Java中的多态
1.多态:具有表现多种形态的能力的特征 父类: public abstract class Animal {public abstract void Say();} 子类: public class ...
- C# 工厂模式+虚方法(接口、抽象方法)实现多态
面向对象语言的三大特征之一就是多态,听起来多态比较抽象,简而言之就是同一行为针对不同对象得到不同的结果,同一对象,在不同的环境下得到不同的状态. 实例说明: 业务需求:实现一个打开文件的控制台程序的d ...
随机推荐
- BBR拥塞算法的简单解释
TCP BBR的ACM论文中,开篇就引入了图1,以此来说明BBR算法的切入点: 为何当前基于丢包探测的TCP拥塞控制算法还有优化空间? BBR算法的优化极限在哪儿? 图1 为了理解这张图花了我整整一个 ...
- java面试一日一题:请讲下对mysql的理解
问题:请讲下对mysql的理解 分析:该问题主要考察对mysql的理解,基本概念及sql的执行流程 回答要点: 主要从以下几点去考虑, 1.mysql的整体架构? 2.mysql中每一个组件的作用? ...
- 大学四年,总结一套适合小白的Java自学路线和方法
前言篇 大家好,我是bigsai 好久不见,甚是想念,文章同时收录在回车课堂(文底阅读原文可达). 无论你是大学生还是在职人员,想学Java时,都会面临两个选择,自学或者报班.报班通常太费钱,时间又不 ...
- 【Redis破障之路】三:Redis单线程架构
众所周知,Redis是一个单线程架构的NoSQL数据库,但是是单线程模型的Redis为什么性能如此之高?这就是我们接下来要探究学习的内容. 1.Redis的单线程架构 1.1.Redis单线程简介 首 ...
- Socket简介 与 UDP
1. Socket 简介 2. UDP 1. Socket 简介 网络编程,是指让在不同的电脑上的软件能够进行数据传递,即进程之间的通信. 本地的进程间通信(IPC) 例如有:队列.同步(互斥锁.条件 ...
- 【Java注解】@PostConstruct 注解相关
不多逼逼,直接看注解上面的文档, @PostConsturct PostConstruct注释用于需要执行的方法在依赖注入完成后执行任何初始化.这个方法必须在类投入服务之前调用. 这个所有支持依赖关系 ...
- PAT 乙级 -- 1013 -- 数素数
题目简介 令Pi表示第i个素数.现任给两个正整数M <= N <= 104,请输出PM到PN的所有素数. 输入格式: 输入在一行中给出M和N,其间以空格分隔. 输出格式: 输出从PM到PN ...
- POJ1094查分约束,判断关系是否唯一
题意: 给你一些a<b的关系,然后有三组询问. 1 当前这组之后如果能确定这n个数的大小关系,那么就输出关系 2 当前时候出现bug,就是和前面如果冲突,那么就不行 3 最后的答案是 ...
- Windows核心编程 第二十章 DLL的高级操作技术
第2 0章 D L L的高级操作技术 看了下这章的内容,谈不上高级,都是些常用相关,但是还是有一些细节需要注意. 20.1 DLL模块的显式加载和符号链接 如果线程需要调用D L L模块中的函数,那么 ...
- 将大量ASCII码值转换成字符函数CHR()的小技巧
一.在学习命令执行漏洞的过程中,遇到以下情况: 当服务器上传不了马或者马被过滤的时候,我们可以迂回一下,通过执行写马命令到服务器,在服务器里面写马,该命令是通过ascii编码过的命令,防止被过滤. 1 ...