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 多态的更多相关文章

  1. Rust 智能指针(一)

    Rust 智能指针(一) 1.Box<T> Box<T>是指向堆中的指针. fn main() { let box = Box::new(3); println!(" ...

  2. Rust 中的类型转换

    1. as 运算符 as 运算符有点像 C 中的强制类型转换,区别在于,它只能用于原始类型(i32 .i64 .f32 . f64 . u8 . u32 . char 等类型),并且它是安全的. 例 ...

  3. rust语法

    目录 rust语法 前言 一.数据类型 1.1 标量scalar 1.2 复合compound 1.3 切片slice 1.4 引用(借用)reference 1.5 智能指针smart pointe ...

  4. Rust学习笔记一 数据类型

    写在前面 我也不是什么特别厉害的大牛,学历也很低,只是对一些新语言比较感兴趣,接触过的语言不算多也不算少,大部分也都浅尝辄止,所以理解上可能会有一些偏差. 自学了Java.Kotlin.Python. ...

  5. the rust book 的简单入门笔记

    rust learning day 1 (2021/05/27) 学了常量,变量,数据类型,控制流,所有权 char 的宽度是4字节,一个 unicode 的宽度 控制流条件都不要括号 rust 中的 ...

  6. rust漫游 - 写时拷贝 Cow<'_, B>

    rust漫游 - 写时拷贝 Cow<'_, B> Cow 是一个写时复制功能的智能指针,在数据需要修改或者所有权发生变化时使用,多用于读多写少的场景. pub enum Cow<'a ...

  7. Rust极简教程

    目录 简介 特性 特征 用途 安装 核心组件 常用命令 基础语法 数据类型 标量类型 复合类型 示例 条件语句 循环 输出&输入 输出 输出花括号 输出非基础类型 输入 所有权 切片 结构体 ...

  8. Java中的多态

    1.多态:具有表现多种形态的能力的特征 父类: public abstract class Animal {public abstract void Say();} 子类: public class ...

  9. C# 工厂模式+虚方法(接口、抽象方法)实现多态

    面向对象语言的三大特征之一就是多态,听起来多态比较抽象,简而言之就是同一行为针对不同对象得到不同的结果,同一对象,在不同的环境下得到不同的状态. 实例说明: 业务需求:实现一个打开文件的控制台程序的d ...

随机推荐

  1. 安装mongoDB出现的问题:无法启动

    在我的电脑- 管理 - 服务-中会出现一个MongoDB Server的服务,你需要去手动删除这个服务删除指令: 在cmd管理员模式下使用: sc delete MongoDB Server 然后再配 ...

  2. [面试仓库]CSS面试题汇总-定位篇

    一,relative.absolute 的区别   我们还是来说常见的地方.首先就是relative,absolute的区别: relative是依据自身来定位的 absolute则是依据离其最近一层 ...

  3. TCP的client和server的简单连接

    server: import socket as s import threading as t bind_ip = "0.0.0.0" bind_port = 80#配置服务器监 ...

  4. SpringBoot项目打包部署

    部署方式 SpringBoot项目可以通过jar包或者war包部署在服务器上,因为jar包更适合前后端分离的项目,所以这里我们使用jar包的方式. 添加maven支持 <!-- 这个插件,可以将 ...

  5. Java网络编程快速上手(SE基础)

    参考资料:百度百科TCP协议 本文涉及Java IO流.异常的知识,可参考我的另外的博客 一文简述Java IO 一文简述JAVA内部类和异常 1.概述 计算机网络相关知识: OSI七层模型 一个报文 ...

  6. 浅析 Find My 原理

    什么是 Find My 网络? 2021年4月21日的苹果发布会发布了一款新的产品:AirTag.使用的是 BLE + UWB 的技术.BLE 和 Find My 网络为 AirTag 提供了 GPS ...

  7. 数栈运维实例:Oracle数据库运维场景下,智能运维如何落地生根?

    从马车到汽车是为了提升运输效率,而随着时代的发展,如今我们又希望用自动驾驶把驾驶员从开车这项体力劳动中解放出来,增加运行效率,同时也可减少交通事故发生率,这也是企业对于智能运维的诉求. 从人工运维到自 ...

  8. java 读取ini文件

    1.情景:需要将硬代码写到文件中,这样以后改动只需改动灵活 1)txt文件,需要将这code字符串读到代码中,保存成数组 2)导包:pom.xml添加依赖: <dependency> &l ...

  9. Weekly Contest 184

    1408. String Matching in an Array Given an array of string words. Return all strings in words which ...

  10. hdu5040 不错的广搜

    题意:       给你一个地图,让你从起点走到终点,然后图上有空地,墙,还有摄像头,摄像头有初始方向,每一秒摄像头都会顺时针旋转90度,每个摄像头有自己的观察范围,它所在的点,和当前它面向的那个点, ...