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

【Rust练习】16.方法和关联函数

练习题来自:https://practice-zh.course.rs/method.html

1 🌟🌟 方法跟函数类似:都是使用 fn 声明,有参数和返回值。但是与函数不同的是,方法定义在结构体的上下文中(枚举、特征对象也可以定义方法),而且方法的第一个参数一定是 self 或其变体 &self 、&mut self,self 代表了当前调用的结构体实例。

struct Rectangle {width: u32,height: u32,
}impl Rectangle {// 完成 area 方法,返回矩形 Rectangle 的面积fn area
}fn main() {let rect1 = Rectangle { width: 30, height: 50 };assert_eq!(rect1.area(), 1500);
}

答案如下

impl Rectangle {// 完成 area 方法,返回矩形 Rectangle 的面积fn area(&self) -> u32{self.width * self.height}
}

说几个我觉得和C++的类成员函数的区别:

  1. 关联方法类似C++的静态方法(static),而方法就是类成员函数了,调用规则和C++是一样的。
  2. self引用类似C++的this指针,但是rust的self引用是强制的,必须写在参数列表里,且访问成员时必须加入self限定;而C++的this指针不是强制的,参数不能写this指针,访问成员也不强制加限定(除非冲突)
  3. 因为第二条,显然Rust的关联方法是不能访问成员变量的,C++的静态方法可以访问静态成员变量。

2 🌟🌟 self 会拿走当前结构体实例(调用对象)的所有权,而 &self 却只会借用一个不可变引用,&mut self 会借用一个可变引用

// 只填空,不要删除任何代码行!
#[derive(Debug)]
struct TrafficLight {color: String,
}impl TrafficLight {pub fn show_state(__)  {println!("the current state is {}", __.color);}
}
fn main() {let light = TrafficLight{color: "red".to_owned(),};// 不要拿走 `light` 的所有权light.show_state();// 否则下面代码会报错println!("{:?}", light);
}

答案

impl TrafficLight {pub fn show_state(&self)  {println!("the current state is {}", self.color);}
}

所有权转移大多用来销毁某些资源,这和C++的析构函数有异曲同工之妙。

3 🌟🌟 &self 实际上是 self: &Self 的缩写或者说语法糖

struct TrafficLight {color: String,
}impl TrafficLight {// 使用 `Self` 填空pub fn show_state(__)  {println!("the current state is {}", self.color);}// 填空,不要使用 `Self` 或其变体pub fn change_state(__) {self.color = "green".to_string()}
}
fn main() {}

self是引用本身,Self其实就是本身类型的别名

impl TrafficLight {// 使用 `Self` 填空pub fn show_state(self: &Self)  {println!("the current state is {}", self.color);}// 填空,不要使用 `Self` 或其变体pub fn change_state(&mut self) {self.color = "green".to_string()}
}

4 🌟🌟 定义在 impl 语句块中的函数被称为关联函数,因为它们跟当前类型关联在一起。关联函数与方法最大的区别就是它第一个参数不是 self ,原因是它们不需要使用当前的实例,因此关联函数往往可以用于构造函数:初始化一个实例对象。

#[derive(Debug)]
struct TrafficLight {color: String,
}impl TrafficLight {// 1. 实现下面的关联函数 `new`,// 2. 该函数返回一个 TrafficLight 实例,包含 `color` "red"// 3. 该函数必须使用 `Self` 作为类型,不能在签名或者函数体中使用 `TrafficLight`pub fn new() pub fn get_state(&self) -> &str {&self.color}
}fn main() {let light = TrafficLight::new();assert_eq!(light.get_state(), "red");
}

基本的一个构造函数,不过C++的构造函数往往是和类同名的,new关键字一般用于在堆上分配内存。

impl TrafficLight {pub fn new(colour: String) -> Self{TrafficLight{color: colour}} pub fn get_state(&self) -> &str {&self.color}
}

5 🌟 每一个结构体允许拥有多个 impl 语句块


struct Rectangle {width: u32,height: u32,
}// 使用多个 `impl` 语句块重写下面的代码
impl Rectangle {fn area(&self) -> u32 {self.width * self.height}fn can_hold(&self, other: &Rectangle) -> bool {self.width > other.width && self.height > other.height}
}fn main() {}

其实我一直很好奇,Rust这种组织方式,项目的结构会不会很难看。

impl Rectangle {fn area(&self) -> u32 {self.width * self.height}
}impl Rectangle {fn can_hold(&self, other: &Rectangle) -> bool {self.width > other.width && self.height > other.height}
}

6 🌟🌟🌟 我们还可以为枚举类型定义方法


#[derive(Debug)]
enum TrafficLightColor {Red,Yellow,Green,
}// 为 TrafficLightColor 实现所需的方法
impl TrafficLightColor {}fn main() {let c = TrafficLightColor::Yellow;assert_eq!(c.color(), "yellow");println!("{:?}",c);
}

需要针对self的值进行匹配,并返回对应的&str,这里给出一种简单的实现:

impl TrafficLightColor {fn color(&self) -> &str{match self {TrafficLightColor::Yellow => "yellow",_ => "default"}}
}

相关文章:

  • 解决远程连接AlpineLinux Mysql/MariaDB 无法连接的问题
  • Nginx反向代理配置支持websocket
  • 第18周 第1章Ajax基础知识
  • Axure原型系统:药企内部管理平台原型设计
  • Html--笔记01:使用软件vscode,简介Html5--基础骨架以及标题、段落、图片标签的使用
  • TypeScript 设计模式之【单例模式】
  • 数据备份策略:保障数据安全的关键
  • 从预测性维护到智能物流:ARM边缘计算控制器的工业实践
  • C++——编写一个函数,求一个字符串的长度。在main函数中输入字符串,并输出其长度。用指针方法处理。
  • 入门插件开发-列表插件开发-第三节:案例演示——setFilter事件讲解
  • LLMs之RAG:MemoRAG(利用其记忆模型来实现对整个数据库的全局理解)的简介、安装和使用方法、案例应用之详细攻略
  • 【自学笔记】支持向量机(4)——支持向量回归SVR
  • 国内可用ChatGPT-4中文镜像网站整理汇总【持续更新】
  • 三.python入门语法2
  • OSPF相关基础介绍及基础配置,网络工程师必修
  • 【面试系列】之二:关于js原型
  • CSS实用技巧
  • DOM的那些事
  • java中具有继承关系的类及其对象初始化顺序
  • Node 版本管理
  • node 版本过低
  • Node项目之评分系统(二)- 数据库设计
  • Python爬虫--- 1.3 BS4库的解析器
  • vagrant 添加本地 box 安装 laravel homestead
  • 从零搭建Koa2 Server
  • 浮现式设计
  • 给github项目添加CI badge
  • 基于OpenResty的Lua Web框架lor0.0.2预览版发布
  • 前端之Sass/Scss实战笔记
  • 用Python写一份独特的元宵节祝福
  • 正则与JS中的正则
  • 《天龙八部3D》Unity技术方案揭秘
  • Play Store发现SimBad恶意软件,1.5亿Android用户成受害者 ...
  • ​七周四次课(5月9日)iptables filter表案例、iptables nat表应用
  • #include到底该写在哪
  • #面试系列-腾讯后端一面
  • (博弈 sg入门)kiki's game -- hdu -- 2147
  • (二十四)Flask之flask-session组件
  • (分类)KNN算法- 参数调优
  • (教学思路 C#之类三)方法参数类型(ref、out、parmas)
  • (三十五)大数据实战——Superset可视化平台搭建
  • (实测可用)(3)Git的使用——RT Thread Stdio添加的软件包,github与gitee冲突造成无法上传文件到gitee
  • (四)c52学习之旅-流水LED灯
  • (续)使用Django搭建一个完整的项目(Centos7+Nginx)
  • (转)Android中使用ormlite实现持久化(一)--HelloOrmLite
  • (转)平衡树
  • @Autowired 与@Resource的区别
  • @Responsebody与@RequestBody
  • [7] CUDA之常量内存与纹理内存
  • [ActionScript][AS3]小小笔记
  • [APUE]进程关系(下)
  • [AX]AX2012 AIF(四):文档服务应用实例
  • [BIZ] - 1.金融交易系统特点
  • [BT]BUUCTF刷题第4天(3.22)
  • [BZOJ5250][九省联考2018]秘密袭击(DP)