【Rust自学】5.3. struct的方法(Method)

喜欢的话别忘了点赞、收藏加关注哦,对接下来的教程有兴趣的可以关注专栏。谢谢喵!(=・ω・=)

5.3.1. 什么是方法(Method)

方法和函数类似,也是用fn关键字进行声明,方法也有名称,也有参数,也有返回值。但方法和函数也有不同之处:

  • 方法在struct(或枚举或trait对象)的上下文中定义
  • 方法的第一个参数总是self,表示方法所在的(被调用的)struct实例,类似于Python中的self和JS中的this

5.3.2. 方法的实际应用

接下来还是看例子,以上一篇文章的代码为例:

struct Rectangle {  
    width: u32,  
    length: u32,  
}  
  
fn main() {  
    let rectangle = Rectangle{  
        width: 30,  
        length: 50,  
    };  
    println!("{}", area(&rectangle));  
}  
  
fn area(dim:&Rectangle) -> u32 {  
    dim.width * dim.length  
}

area这个函数的作用是计算面积,但它很特别,它只适用于矩形而不适用于其他形状或者是其他的类型。如果后面代码中要加上计算其他图形的面积的函数,那么area这个名字就要混淆。如果改名成ractangle_area的话又太麻烦,main函数里所有调用了这个函数的地方都要改。

所以如果能把存储矩形长款的Rectangle结构体和只能计算矩形面积area这个函数结合到一起就是最好的。

对于这种需求,Rust提供了implementation(中文意为实现),其关键字是impl,后边跟着struct名,加上{},在里面像定义普通函数一样定义方法就行。

对于这个例子,struct名就是Rectangle,把定义area函数的代码剪贴到{}内即可。

impl Rectangle {  
    fn area(dim:&Rectangle) -> u32 {  
        dim.width * dim.length  
    }  
}

但注意这里的代码还不是方法,因为方法的第一个参数必须是self,现在的代码叫关联函数,下文会讲。

这么写是没有问题的,但还可以进一步简化。上文中说到了方法的第一个参数总是self,所以这里也可以改一下:

impl Rectangle {  
    fn area(&self) -> u32 {  
        self.width * self.length  
    }  
}

你当前写的这个方法绑定在谁上,self指的就是谁,这个代码中area这个函数被绑定在Rectangle上,所以self就指的是Rectanglearea的参数不用拿走所有权,所以在self前面加上&表示印引用。

当然这么改之后,main函数里的函数调用也会改,从函数的调用改到方法的调用——实例.方法名(参数):

fn main() {  
    let rectangle = Rectangle{  
        width: 30,  
        length: 50,  
    };  
    println!("{}", rectangle.area());  
}

rectangle.area()的括号中不写东西是因为area方法在定义时只使用了&self作为参数,表示这个方法借用了self(即rectangle实例)的不可变引用。在调用area时,你不需要显式地传递这个实例,因为方法调用已经隐式地知道selfrectangle

整体代码如下:

struct Rectangle {  
    width: u32,  
    length: u32,  
}  
  
impl Rectangle {  
    fn area(&self) -> u32 {  
        self.width * self.length  
    }  
}  
  
fn main() {  
    let rectangle = Rectangle{  
        width: 30,  
        length: 50,  
    };  
    println!("{}", rectangle.area());  
}

输出:

1500

5.3.3. 如何定义方法

在上面的实际应用中已经写过一遍了,所以这里就只做总结:

  • impl里定义方法
  • 方法的第一个参数可以是self&self或是&mut self。可以是获得所有权、引用或可变引用,这点和其他参数一样。
  • 方法可以帮助更好的组织代码,因为可以把某个类型的方法都放在impl块里面,避免在整个代码库里搜索struct它相关的行为了。

5.3.4. 方法调用的运算符

在C/C++中,调用方法有两种运算符

  • ->:其格式为object->something(),调用指针指向的对象上的方法就使用这一种(也就是object为指针时)
  • .:其格式为object.something(),调用对象上的方法就使用这种(也就是object不为指针,是个对象时)

object->something()实际上是语法糖,它等同于(*object).something()*表示解引用。两者的流程都是先解引用,得到对象,再在对象上调用方法。

Rust提供了自动引用/解引用的特性。也就是说,在调用方法时,Rust根据情况自动添加&&mut*,以便object可以匹配方法的签名。这点和Go语言一样。

举个例子,下面这两行代码效果相同:

point1.distance(&point2);
(&point1).distance(&point2);

Rust会根据情况自动在point1前加上&

5.3.5. 方法的参数

方法除了self也可以带其他参数,一个或多个都可以。

举个例子,在5.3.2的代码基础上加一个判断矩形是否能容纳下另一个长方形的功能(不考虑斜着放,也不考虑矩形的长比宽长的情况)

impl Rectangle {  
    fn can_hold(&self, other: &Rectangle) -> bool {  
        self.width > other.width && self.length > other.length  
    }  
}

逻辑非常好想,只要矩形的长和宽都比另一个大就行。

然后再在main函数里写几个Rectangle的实例,输出比较结果看看有没有问题就行,以下是完整代码:

struct Rectangle {  
    width: u32,  
    length: u32,  
}  
  
impl Rectangle {  
    fn can_hold(&self, other: &Rectangle) -> bool {  
        self.width > other.width && self.length > other.length  
    }  
}  
  
fn main() {  
    let rect1 = Rectangle{  
        width: 30,  
        length: 50,  
    };  
    let rect2 = Rectangle{  
        width: 10,  
        length: 40,  
    };  
    println!("{}", rect1.can_hold(&rect2));  
}

输出:

true

5.3.6. 关联函数

可以在impl块里定义不把self作为第一个参数的函数,叫关联函数(不是方法)。它不是在实例上调用的,但它与这个类型有关联。例如: String::from()就是String这个类型上叫做from的关联函数。

关联函数通常用于构造器,也就是用来被创建关联类型的一个实例。

比如说,在5.3.2的代码基础上加一个构建正方形的构造器(正方形也是特殊的矩形):

impl Rectangle {  
    fn square(size: u32) -> Rectangle {  
        Rectangle{  
            width: size,  
            length: size,  
        }  
    }  
}

参数只需要一个,因为构造正方形只需要一个边长。

main函数里调用一下这个关联函数试试,其格式为类型名::函数名(参数),以下是完整代码:

#[derive(Debug)]  
struct Rectangle {  
    width: u32,  
    length: u32,  
}  
  
impl Rectangle {  
    fn square(size: u32) -> Rectangle {  
        Rectangle{  
            width: size,  
            length: size,  
        }  
    }  
}  
  
fn main() {  
    let square = Rectangle::square(10);  
    println!("{:?}", square);  
}

输出:

Rectangle { width: 10, length: 10 }

::不仅可以用于关联函数,也可以用于模块创建命名空间(以后会讲)

5.3.7. 多个impl块

每个struct允许拥有多个impl块。

比如我要把这篇文章里写过的所有的方法和关联函数都写到代码里。
可以这么写(多个impl块):

#[derive(Debug)]  
struct Rectangle {  
    width: u32,  
    length: u32,  
}  
  
impl Rectangle {  
    fn area(&self) -> u32 {  
        self.width * self.length  
    }  
}  
  
impl Rectangle {  
    fn can_hold(&self, other: &Rectangle) -> bool {  
        self.width > other.width && self.length > other.length  
    }  
}  
  
impl Rectangle {  
    fn square(size: u32) -> Rectangle {  
        Rectangle{  
            width: size,  
            length: size,  
        }  
    }  
}  
  
fn main() {  
    let square = Rectangle::square(10);  
    println!("{:?}", square);  
}

也可以这么写(合在一个impl块里):

#[derive(Debug)]  
struct Rectangle {  
    width: u32,  
    length: u32,  
}  
  
impl Rectangle {  
    fn area(&self) -> u32 {  
        self.width * self.length  
    }  
  
    fn can_hold(&self, other: &Rectangle) -> bool {  
        self.width > other.width && self.length > other.length  
    }  
  
    fn square(size: u32) -> Rectangle {  
        Rectangle{  
            width: size,  
            length: size,  
        }  
    }  
}  
  
fn main() {  
    let square = Rectangle::square(10);  
    println!("{:?}", square);  
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/943070.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络实验室建设方案

一、计算机网络实验室拓扑结构 计算机网络综合实验室解决方案,是面向高校网络相关专业开展教学实训的综合实训基地解决方案。教学实训系统采用 B/S架构,通过公有云教学实训平台在线学习模式,轻松实现网络系统建设与运维技术的教学…

ThinkPHP 8开发环境安装

【图书介绍】《ThinkPHP 8高效构建Web应用》-CSDN博客 《ThinkPHP 8高效构建Web应用 夏磊 编程与应用开发丛书 清华大学出版社》【摘要 书评 试读】- 京东图书 1. 安装PHP8 Windows系统用户可以前往https://windows.php.net/downloads/releases/archives/下载PHP 8.0版本&am…

Nmap基础入门及常用命令汇总

Nmap基础入门 免责声明:本文单纯分享技术,请大家使用过程中遵守法律法规~ 介绍及安装 nmap是网络扫描和主机检测的工具。作为一个渗透测试人员,必不可少的就是获取信息。那么nmap就是我们从互联网上获取信息的途径,我们可以扫描互…

使用openvino加速部署paddleocr文本方向分类模型(C++版)

使用openvino加速部署paddleocr文本方向分类模型(C++版) 大体流程方向分类器在openvino上的部署代码C++大体流程 原始图像: 先resize 再归一化 方向分类器在openvino上的部署代码C++ #include <iostream> #include <string>#include <vector> #i…

嵌入式单片机窗口看门狗控制与实现

窗口看门狗 注意:WWDG外设没有独立的时钟源,而是挂载在APB1总线下,APB1总线外设时钟为42MHZ。 了解WWDG外设的使用流程,可以参考stm32f4xx_wwdg.c的开头注释,具体流程如下图所示

【KLEE】源码阅读笔记----KLEE执行流程

本文架构 1. 动机2.KLEE简介3.KLEE的代码工程结构4. 从KLEE主函数入手main函数step1: 初始化step2&#xff1a;加载.bc文件进行符号执行 读取测试用例输出日志信息 1. 动机 最近准备对KLEE进行修改使其符合我的需要&#xff0c;因此免不了需要对源码进行修改。读懂源码是对在其…

【hackmyvm】soul靶机wp

tags: HMVrbash绕过图片隐写PHP配置解析 1. 基本信息^toc 文章目录 1. 基本信息^toc2. 信息收集3. 图片解密3.1. 爆破用户名3.2. 绕过rbash3.3. 提权检测 4. 获取webshell4.1. 修改php配置 5. www-data提权gabriel6. gabriel提取到Peter7. Peter提权root 靶机链接 https://ha…

macos 隐藏、加密磁盘、文件

磁盘加密 打开磁盘工具 点击添加 设置加密参数 设置密码 查看文件 不用的时候右键卸载即可使用的时候装载磁盘&#xff0c;并输入密码即可 修改密码 解密 加密&#xff0c;输入密码即可 禁止开机自动挂载此加密磁盘 如果不禁止自动挂载磁盘&#xff0c;开机后会弹出输入…

基于OpenCV和Python的人脸识别系统_django

开发语言&#xff1a;Python框架&#xff1a;djangoPython版本&#xff1a;python3.7.7数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat11开发软件&#xff1a;PyCharm 系统展示 管理员登录 管理员功能界面 用户管理 公告信息管理 操作日志管理 用户登录界面 用户…

如何永久解决Apache Struts文件上传漏洞

Apache Struts又双叒叕爆文件上传漏洞了。 自Apache Struts框架发布以来&#xff0c;就存在多个版本的漏洞&#xff0c;其中一些漏洞涉及到文件上传功能。这些漏洞可能允许攻击者通过构造特定的请求来绕过安全限制&#xff0c;从而上传恶意文件。虽然每次官方都发布补丁进行修…

回归预测 | MATLAB实现CNN-LSTM卷积长短期记忆神经网络多输入单输出回归预测

回归预测 | MATLAB实现CNN-LSTM卷积长短期记忆神经网络多输入单输出回归预测 目录 回归预测 | MATLAB实现CNN-LSTM卷积长短期记忆神经网络多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 MATLAB实现CNN-LSTM卷积长短期记忆神经网络多输入单输出回归…

LeetCode - Google 校招100题 第5天 双指针(Two Pointers) (11题)

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/144742777 LeetCode 合计最常见的 112 题: 校招100题 第1天 链表(List) (19题)校招100题 第2天 树(Tree) (21题)校招100题 第3天 动态规划(DP) (20题)

【无人机】无人机测绘路径优化策略与实践:探索高效、精准的测绘技术路径

&#x1f351;个人主页&#xff1a;Jupiter. &#x1f680; 所属专栏&#xff1a;传知代码 欢迎大家点赞收藏评论&#x1f60a; 目录 一、背景介绍二、算法原理&#xff08;一&#xff09;算法模型构建&#xff08;二&#xff09;算法求解流程 三、代码实现&#xff08;一&…

Anaconda搭建Python虚拟环境并在Pycharm中配置(小白也能懂)

为什么要搭建虚拟环境&#xff1f; 搭建虚拟环境的主要目的是为了解决多个Python项目之间可能存在的库冲突问题。当你在同一台计算机上运行多个Python项目时&#xff0c;不同的项目可能会依赖于不同版本的库或者相同版本的库的不同补丁。如果所有项目都共享相同的Python环境&am…

mac_录屏

参考&#xff1a; mac m1上系统内录方法BlackHole代替soundflower录音(附安装包) https://blog.csdn.net/boildoctor/article/details/122765119录屏后没声音&#xff1f;这应该是 Mac&#xff08;苹果电脑&#xff09; 内录声音最优雅的解决方案了 https://www.bilibili.com/…

upload-labs关卡记录13

这里和关卡12非常类似&#xff0c;唯一不同就是12关用到get方法&#xff0c;这里用到post方法。因此对应的截断方式也不一样&#xff0c;依旧是使用我们的bp进行抓包&#xff0c; 然后依旧是在upload后加上shell.php&#xff0c;这里用是为了hex时好区别我们要在哪里更改&#…

网络管理-期末项目(附源码)

环境&#xff1a;网络管理 主机资源监控系统项目搭建 &#xff08;保姆级教程 建议点赞 收藏&#xff09;_搭建网络版信息管理系统-CSDN博客 效果图 下面3个文件的项目目录(python3.8.8的虚拟环境) D:\py_siqintu\myproject5\Scripts\mytest.py D:\py_siqintu\myproject5\Sc…

通过GRE协议组建VPN网络

GRE&#xff08;Generic Routing Encapsulation&#xff0c;通用路由封装协议&#xff09;协议是一种简单而有效的封装协议&#xff0c;它在网络中的广泛应用&#xff0c;比如在构建VPN网络。   GRE是一种封装协议&#xff0c;它允许网络层协议&#xff08;如IP&#xff09;的…

kafka的备份策略:从备份到恢复

文章目录 一、全量备份二、增量备份三、全量恢复四、增量恢复 前言&#xff1a;Kafka的备份的单元是partition&#xff0c;也就是每个partition都都会有leader partiton和follow partiton。其中leader partition是用来进行和producer进行写交互&#xff0c;follow从leader副本进…

CHM助手 >> 如何安装CHM助手

1 如何安装CHM助手 下载CHM助手.ezip&#xff0c;下载地址打开EverEdit&#xff0c;选择主菜单“扩展 -> 扩展管理 -> 从本地文件安装扩展”&#xff0c;在弹出的文件浏览窗口中选择插件安装包&#xff0c;如下图所示&#xff1a; &#x1f56e;说明&#xff1a;   …