当前位置: 首页 > news >正文

【rust语言】rust多态实现方式

文章目录

  • 前言
  • 一、多态
  • 二、rust实现多态
    • trait的静态方式
    • 还有一种方式可以通过动态分发,还以上面那段代码,比如
        • dyn关键字
    • 泛型方式
    • 枚举方式
      • 优点:
      • 缺点:
  • 总结


前言

学习rust当中遇到了这个问题,记录一下,不对地方望指正

一、多态

多态是面向对象程序设计中的一个重要概念,指同一个行为或操作在不同实例上具有不同的行为或结果。简单来说,多态就是指同一种类型的对象,在不同的上下文中有不同的行为。多态性使得程序可以更加灵活、可扩展和易于维护。在实现多态性时,通常会使用继承、接口、抽象类等技术

二、rust实现多态

trait的静态方式


trait Animal {fn make_sound(&self);
}
struct Cat {}impl Animal for Cat {fn make_sound(&self) {println!("Meow");}
}
struct Dog {}impl Animal for Dog {fn make_sound(&self) {println!("Woof");}
}fn main() {let cat: Cat = Cat {};let dog: Dog = Dog {};test(cat);test(dog)
}
//接受Animal Trait类型的
fn test(animal : impl Animal){animal.make_sound()
}

定义了方法传入参数是trait。这一种在实例化的时候是具体的类型,在传参的时候编译器能推断出来具体是cat还是dog,能调用具体方法

还有一种方式可以通过动态分发,还以上面那段代码,比如

trait Animal {fn make_sound(&self);
}struct Cat {}impl Animal for Cat {fn make_sound(&self) {println!("Meow");}
}struct Dog {}impl Animal for Dog {fn make_sound(&self) {println!("Woof");}
}fn main() {let cat: Box<dyn Animal> = Box::new(Cat {});let dog: Box<dyn Animal> = Box::new(Dog {});test(cat);test(dog)
}fn test(animal: Box<dyn Animal>) {animal.make_sound()
}

这种方式相对于上面更加灵活,因为实例化参数变量类型是trait类型。现在说说关键点

dyn关键字

dyn关键字是在Rust中用于创建和使用动态分发的trait对象的关键字。trait对象允许我们以统一的方式处理不同类型的对象,并使用相同的方法调用语法。使用动态分发,编译器无需在编译时知道具体的类型,而是在运行时根据对象的实际类型来确定要调用的方法。要创建一个trait对象,需要在trait名称前加上dyn关键字。例如,对于名为TraitName的trait,我们可以使用dyn TraitName来创建一个trait对象。

trait TraitName {// trait定义
}fn main() {let trait_obj: Box<dyn TraitName> = Box::new(ConcreteType);// 在这里使用trait对象
}

在上面的代码中,trait_obj是一个Box指向动态分发的trait对象的指针。它可以存储实现了TraitName trait的任何具体类型的对象。通过dyn关键字,我们可以在运行时根据实际类型来调用trait定义的方法。
这里要注意,trait对象通过指针或引用来操作,因此通常结合使用Box、&或&mut来创建和使用trait对象。为了在运行时确定对象的大小,我们需要将它们放置在一个固定大小的容器中。这就是为什么要使用Box来包装trait对象的原因。Box类型表示一个动态分发的trait对象。它在堆上分配一块内存,该内存用于存储对象的数据,并提供一个指向虚函数表(vtable)的指针,该表用于在运行时查找和调用正确的方法。
这种方式相对于静态方式会更加灵活,但会有运行时性能损失,看情况决定使用哪一种

泛型方式

use std::fmt::{Display, Formatter};struct Cat {}struct Dog {}impl Display for Cat{fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {write!(f,"Cat")}
}impl Display for Dog{fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {write!(f,"Dog")}
}fn make_sound<T: Display>(animal: T) {println!("{}", animal);
}fn main() {make_sound(Cat{});make_sound(Dog{});
}

通过在函数签名中使用泛型类型参数,函数可以接受不同类型的参数,并在编译时生成对应的具体化代码。这种方式不依赖于trait,而是基于类型推断和编译时的静态分发

枚举方式

还有一种方式是使用枚举方式,例如

enum Shape {Circle(f64),Square(f64),Rectangle(f64, f64),
}impl Shape {fn area(&self) -> f64 {match *self {Shape::Circle(radius) => std::f64::consts::PI * radius * radius,Shape::Square(side_length) => side_length * side_length,Shape::Rectangle(length, width) => length * width,}}
}fn main() {let circle = Shape::Circle(5.0);let square = Shape::Square(4.0);let rectangle = Shape::Rectangle(3.0, 6.0);test(circle);test(square);test(rectangle);
}fn test(shape: Shape) {println!("shape area: {}", shape.area());
}

枚举在实现多态性方面有一些优点和缺点。以下是其中的一些:

优点:

简洁性:枚举提供了一种紧凑的方式来定义和组织具有不同变体的数据类型。它能够在一个地方集中描述和管理多种可能的状态或情况。
静态类型检查:由于枚举的变体是预先定义的,编译器可以在编译时验证变体的正确性。这可以帮助捕捉到潜在的错误,并提供类型安全性。
模式匹配:枚举与模式匹配相结合,可以使代码更具表达力和可读性。模式匹配可以根据具体的变体类型执行相应的逻辑,同时处理所有可能的情况,避免遗漏。

缺点:

限制的扩展性:当需要添加新的变体时,枚举需要进行修改。这可能涉及到修改已有的代码,以适应新的变体。这对于外部库或包的枚举类型来说尤其困难,因为无法直接修改其定义。
冗余的结构:枚举的每个变体都可以存储不同的数据结构,这可能会导致某些变体拥有与其他变体不相关的冗余数据。这可能会浪费内存空间,尤其是当只使用其中的一部分变体时。
灵活性的限制:枚举要求提前定义所有可能的变体。如果需要在运行时动态添加新的变体,或者处理不确定的类型集合,那么枚举可能不适合。

总结

以上就是今天要说的内容,不对的地方望指正

相关文章:

【rust语言】rust多态实现方式

文章目录 前言一、多态二、rust实现多态trait的静态方式还有一种方式可以通过动态分发&#xff0c;还以上面那段代码&#xff0c;比如dyn关键字 泛型方式枚举方式优点&#xff1a;缺点&#xff1a; 总结 前言 学习rust当中遇到了这个问题&#xff0c;记录一下&#xff0c;不对…...

两年半机场,告诉我如何飞翔

为说明如何坐飞机离港&#xff0c;故此记录一篇。何为离港&#xff0c;顾名思义&#xff0c;离开港湾&#xff0c;那何为港湾&#xff0c;便是机场。 机场&#xff0c;一个你可能经常去&#xff0c;亦或不曾去之地。我想&#xff0c;管你去没去过&#xff0c;先说下怎么去&…...

【动手学深度学习】--21.锚框

锚框 学习视频&#xff1a;锚框【动手学深度学习v2】 官方笔记&#xff1a;锚框 1.锚框 目标检测算法通常会在输入图像中采样大量的区域&#xff0c;然后判断这些区域中是否包含我们感兴趣的目标&#xff0c;并调整区域边界从而更准确地预测目标的真实边界框&#xff08;gro…...

C语言学习笔记(完整版)

文章目录 算法算法的基本概念算法的特征算法的优劣 描述算法三种基本结构流程图N-S流程图伪代码 常量和变量了解数据类型常量整形常量实型常量字符型常量转义字符符号常量 变量整形变量实型变量字符型变量 表达式与运算符赋值运算符和赋值表达式变量赋初值强制类型转换 算术运算…...

【Unity3D赛车游戏】【四】在Unity中添加阿克曼转向,下压力,质心会让汽车更稳定

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;Uni…...

Python爬虫requests判断请求超时并重新post/get发送请求

在使用Python爬虫中&#xff0c;你可以使用requestsimport requests #Python爬虫requests判断请求超时并重新post发送请求&#xff0c;proxies为代理 def send_request_post(url, data, headers , proxies , max_retries3, timeout5):retries 0while retries < max_retries…...

CSS中如何实现多列布局?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 多列布局&#xff08;Multi-column Layout&#xff09;⭐ column-count⭐ column-width⭐ column-gap⭐ column-rule⭐ column-span⭐ 示例⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧…...

【C++】string简单实用详解

本片要分享的内容是有关于string的知识&#xff0c;在这之前得介绍一下什么是STL&#xff1b; 目录 1.STL简单介绍 2. string简单介绍 3.string简单使用 3.1.string的定义 3.2.字符串的拼接 3.3.string的遍历 3.3.1.循环遍历 3.3.2.迭代器遍历 4.string的函数构造 1.…...

opencv 进阶16-基于FAST特征和BRIEF描述符的ORB(图像匹配)

在计算机视觉领域&#xff0c;从图像中提取和匹配特征的能力对于对象识别、图像拼接和相机定位等任务至关重要。实现这一目标的一种流行方法是 ORB&#xff08;Oriented FAST and Rotated Brief&#xff09;特征检测器和描述符。ORB 由 Ethan Rublee 等人开发&#xff0c;结合了…...

Unity 类Scene窗口相机控制

类Scene窗口相机控制 &#x1f354;效果 &#x1f354;效果 传送门&#x1f448;...

juc基础(三)

目录 一、读写锁 1、读写锁介绍 2、ReentrantReadWriteLock 3、例子 4、小结 二、阻塞队列 1、BlockingQueue 简介 2、BlockingQueue 核心方法 3、案例 4、常见的 BlockingQueue &#xff08;1&#xff09;ArrayBlockingQueue(常用) &#xff08;2&#xff09;Li…...

c语言函数指针和指针函数的区别,以及回调函数的使用。

函数指针是什么&#xff0c;函数指针本质也是指针&#xff0c;不过是指向函数的指针&#xff0c;存储的是函数的地址。 指针函数是什么,指针函数其实就是返回值是指针的函数&#xff0c;本质是函数。 函数指针是如何定义的呢&#xff0c;如下 void (*pfun)(int a,int b) 这…...

什么是服务端渲染?前后端分离的优点和缺点?

一.概念 服务端渲染简单点就是服务端直接返回给客户端一个完整的页面&#xff0c;也就是一个完整的html页面&#xff0c;这个页面上已经有数据了。说到这里你可能会觉得后端怎么写页面啊&#xff0c;而且服务端返回页面不是加载更慢吗&#xff1f;错了&#xff0c;因为我们现在…...

【Java】优化重复冗余代码的8种方式

文章目录 前言1. 抽取公用方法2. 抽工具类3. 反射4.泛型5. 继承与多态6.使用设计模式7.自定义注解(或者说AOP面向切面)8.函数式接口和Lambda表达式 前言 日常开发中&#xff0c;我们经常会遇到一些重复代码。大家都知道重复代码不好&#xff0c;它主要有这些缺点&#xff1a;可…...

rabbitmq卸载重新安装3.8版本

卸载之前的版本的rabbitmq 卸载rabbitmq 卸载前先停止rabbitmq服务 /usr/lib/rabbitmq/bin/rabbitmqctl stop查看rabbitmq安装的相关列表 yum list | grep rabbitmq卸载rabbitmq相关内容 yum -y remove rabbitmq-server.noarch 卸载erlang 查看erlang安装的相关列表 …...

MyBatis分页思想和特殊字符

目录 一、MyBatis分页思想 1.1 使用场景 1.2 代码演示 二、MyBatis特殊字符 2.1代码演示 一、MyBatis分页思想 1.1 使用场景 Mybatis分页应用场景&#xff1a; MyBatis是一个Java持久层框架&#xff0c;它提供了一种将SQL查询和结果映射到Java对象的简单方式。分页是MyBa…...

设计模式大白话——命令模式

命令模式 一、概述二、经典举例三、代码示例&#xff08;Go&#xff09;四、总结 一、概述 ​ 顾名思义&#xff0c;命令模式其实和现实生活中直接下命令的动作类似&#xff0c;怎么理解这个命令是理解命令模式的关键&#xff01;&#xff01;&#xff01;直接说结论是很不负责…...

[线程/C++(11)]线程池

文章目录 一、C实现线程池1. 头文件2. 测试部分 二、C11实现线程池1. 头文件2. 测试部分 一、C实现线程池 1. 头文件 #define _CRT_SECURE_NO_WARNINGS #pragma once #include<iostream> #include<string.h> #include<string> #include<pthread.h> #…...

VR防地质灾害安全教育:增强自然灾害知识,提高自我保护意识

VR防地质灾害安全教育系统是一种虚拟仿真技术&#xff0c;可以通过虚拟现实技术模拟地震、泥石流、滑坡等地质灾害的发生和应对过程&#xff0c;帮助人们提高应对突发自然灾害的能力。这种系统的优势在于可以增强自然灾害知识&#xff0c;提高自我保护意识&#xff0c;锻炼人们…...

Mybatis多对多查询案例!

在MyBatis中执行多对多查询需要使用两个主要表和一个连接表&#xff08;通常称为关联表&#xff09;来演示。在这个示例中&#xff0c;我们将使用一个示例数据库模型&#xff0c;其中有三个表&#xff1a;students、courses 和 student_courses&#xff0c;它们之间建立了多对多…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

Go 语言接口详解

Go 语言接口详解 核心概念 接口定义 在 Go 语言中&#xff0c;接口是一种抽象类型&#xff0c;它定义了一组方法的集合&#xff1a; // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的&#xff1a; // 矩形结构体…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

MMaDA: Multimodal Large Diffusion Language Models

CODE &#xff1a; https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA&#xff0c;它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

P3 QT项目----记事本(3.8)

3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

Android第十三次面试总结(四大 组件基础)

Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成&#xff0c;用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机&#xff1a; ​onCreate()​​ ​调用时机​&#xff1a;Activity 首次创建时调用。​…...

排序算法总结(C++)

目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指&#xff1a;同样大小的样本 **&#xff08;同样大小的数据&#xff09;**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...