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 ...
随机推荐
- Python基础(二十一):面向对象“类”第四课——魔法方法
先划一下重点: 6个魔法方法: 动态操作属性的4个函数: 魔法方法 魔法方法的简单介绍 魔法方法的命名规则:方法名(前后各有2个下划线). 通常情况下,不会主动去调用魔法方法,而是在满足一定的条件下, ...
- (Collection, List, 泛型)JAVA集合框架一
Java集合框架部分细节总结一 Collection List 有序,有下标,元素可重复 Set 无序,无下标,元素不可重复 以上为Collection接口 以ArrayList为实现类实现遍历:增强 ...
- gdb常用命令(转)
pwn常常会用到gdb,看到一篇不错的文章,记录了很多命令:https://www.jianshu.com/p/c3e5f5972b21 gdb 基础调试命令 s step,si步入 n 执行下一条指 ...
- Linux Nvidia显卡驱动安装
1 概述 因为某些需要需要在Linux上安装显卡驱动,这里记录一下安装过程. 2 环境 Manjaro RTX 2060 3 下载驱动安装包 到官网上搜索下载即可,可以戳这里: 选择自己的显卡型号即可 ...
- [Vue warn]: Unknown custom element: <terminal-process> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
Vue组件注册报错问题 import 不要加{},排查出如果页面引用单个组件的时候不要加上{}中括号,引入多个组件时才能派上用场,中括号去除问题即可解决.
- Neo4j/cypher学习笔记与学习建议
简介 本笔记的主要内容是 cypher 查询语言的编写与使用. 笔记主要整理自w3cschool上的neo4j教程以及Neo4j中文网所提供的cypher中文文档,此外还包括少量从其他个人博客与官方手 ...
- JAVAEE_Servlet_02_Servlet接口实现类HttpServlet
Servlet接口实现类 * Servlet接口: Servlet接口是来自于Servlet规范下的一个接口,存在于HTTP服务器(Tomcat)所提供的jar包中.Servlet-api.jar. ...
- Tomcat配置及网站创建教程(IDEA)
Tomcat在本机的配置 解压 解压Tomcat压缩包后就算安装完成,解压完成生成文件夹 配置环境变量 1.配置JAVA_HOME 控制面板--系统--查看高级系统设置--环境变量--系统环境变量 新 ...
- mysql 随机选取一条符合条件的记录
暂时记录下: SELECT * FROM `kw_user` AS t1 JOIN ( SELECT ROUND( RAND( ) * ( ( SELECT MAX( id ) FROM `kw_u ...
- LA3177长城守卫
题意: 有n个人围成一个圈,每个人都有r[i]个礼物,任意两个相邻的人的礼物不能有重复的,问满足所有相邻不重复的最少礼物种数是多少?就是问最少多少种礼物能让任意相邻的两个人的礼物不重复. 思 ...