Rust之包、单元包及模块

news2024/12/23 15:34:48
  • 包:一个用于构建、测试并分享单元包的Cargo功能;
  • 单元包:一个用于生成库或可执行文件的树形模块结构;
  • 模块及use关键字:被用于控制文件结构、作用域及路径的私有性;
  • 路径:一种用于命名条目的方法,这些条目包括结构体、函数和模块等。

1、包与单元包:

单元包可以被用于生成二进制程序或库。将Rust编译时所使用的入口文件称作这个单元包的根节点,它同时也是单元包的根模块。
包由一个或多个提供相关功能的单元包集合而成,它所附带的配置文件Cargo.toml描述了如何构建这些单元包的信息。
包包含的规则:

  • 一个包中只能拥有最多一个库单元包;
  • 包可以拥有任意多个二进制单元包;
  • 包内必须存在至少一个单元包(库单元包或二进制单元包)。

Cargo会默认将src/main.rs视作一个二进制单元包的根节点而无需指定,这个二进制单元包与包拥有相同的名称。当包中同时存在src/main.rssrc/lib.rs时,就会分别存在一个二进制单元包与一个库单元包,它们拥有与包相同的名称,可以在路径src/bin下添加源文件来创建出更多的二进制单元包,这个路径下的每个源文件都会被视作单独的二进制单元包。
单元包可以将相关的功能分组,并放到同一作用域下,这样便可以使这些功能轻松地在多个项目中共享。
将单元包的功能保留在它们自己的作用域中有助于指明某个特定功能来源于哪个单元包,并避免可能的命名冲突。

2、通过定义模块来控制作用域及私有性:

模块允许将单元包内的代码按照可读性与易用性来进行分组,同时还允许控制条目的私有性。即模块决定了一个条目是否可以被外部代码使用(公用),或者仅仅只是一个内部的实现细节而不对外暴露(私有)。
模块内可以继续定义其他模块,也同样可以包含其他条目的定义,例如:结构体、枚举、常量、trait等。
在Rust中src/main.rssrc/lib.rs被称为单元包的根节点,这两个文件的内容各自组成了一个名为crate的模块,并位于单元包模块结构的根部。这个模块结构也被称为模块树
模块树的结构:
在这里插入图片描述
当模块A被包含在模块B内时,将模块A称为模块B的子节点,模块B称为模块A的父节点。

3、用于在模块树中指明条目的路径:

为了在Rust的模块树中找到某个条目,同样需要使用路径。例如,在调用某个函数的时候,必须知道它的路径。
路径有两种形式:

  • 使用单元包名或字面量crate从根节点开始的绝对路径;
  • 使用self、super或内部标识符从当前模块开始的相对路径。

绝对路径与相对路径都由至少一个标识符组成,标识符之间使用双冒号::分隔。
Rust中的所有条目(函数、方法、结构体、枚举、模块及常量)默认都是私有的。处于父级模块中的条目无法使用子模块中的私有条目,但子模块中的条目可以使用它所有祖先模块中的条目。虽然子模块包装并隐藏了自身的实现细节,但它却依然能够感知当前定义环境中的上下文。

(1)、使用pub关键字来暴露路径:

为了能够让父模块中可以正常访问子模块中的函数,可以使用关键字pub来标记函数。示例:

mod front_of_house{
	pub mod hosting{
		pub add_to_waitlist(){}
	}
}
pub fn eat_at_restaurant() {
	 // 绝对路径
	 crate::front_of_house::hosting::add_to_waitlist();
	 // 相对路径
	 front_of_house::hosting::add_to_waitlist();
}

注意:仅将父模块设为pub,在访问时,子模块仍是私有的,对外不可见,需要将要调用的最终模块也设置为pub。一个模块的同级节点之间的访问不需要使用关键字pub

(2)、使用super关键字开始构造相对路径:

可以从父模块开始构造相对路径,这一方式需要在路径起始处使用super关键字。
示例:

fn serve_order(){}
mod back_of_house {
	fn fix_incorrect_order(){
		cook_order();
		super::serve_order();
	}
}

由于fix_incorrect_order函数处于back_of_house模块内,所以可以使用super关键字来跳转至back_of_house的父模块,也就是根模块处。从它开始,可以成功地找到 serve_order。

(3)、将结构体或枚举声明为公共的:

结构体和枚举都可以使用pub来声明为公共的,但是二者存在一定的差异。当在结构体前面使用pub时,结构体本身就成为了公共结构体,但是它的字段依旧保持了私有状态。可以逐一决定是否将某个字段公开。
示例:

mod back_of_house {
	pub struct Breakfast {
		pub toast: String,
		seasonal_fruit: String,
	}
	impl Breakfast {
		 pub fn summer(toast: &str) -> Breakfast {
			 Breakfast {
				 toast: String::from(toast),
				 seasonal_fruit: String::from("peaches"),
			 }
		 }
	 }
}

这里的toast是公共的,所以可以在别的函数中使用点号读写,但是seasonal_fruit字段是私有的,不可以直接使用点号进行读写。因为back_of_house::Breakfast拥有了一个私有字段,所以这个结构体需要提供一个公共的关联函数来构造Breakfast的实例(也就是本例中的summer)。如果缺少了这样的函数,将无法在别的函数中中创建任何的Breakfast实例。
与结构体不同的是,将一个枚举声明为公共的时,它所有的变体都自动变为了公共的,仅需要在enum关键字前放置pub。
示例:

mod back_of_house{
	pub enum Appetizer{
		Soup,
		Salad,
	}
}

这里的Soup和Salad都具有公共属性。

4、用use关键字将路径导入作用域:

借助关键字use可以将路径引入作用域,并像使用本地条目一样来调用路径中的目录。

mod front_of_house {
 pub mod hosting {
 pub fn add_to_waitlist() {}
 }
}
use crate::front_of_house::hosting;
pub fn eat_at_restaurant() {
 hosting::add_to_waitlist();
 hosting::add_to_waitlist();
 hosting::add_to_waitlist();
}

使用use来指定相对路径稍有一些不同。必须在传递给use的路径的开始处使用关键字self,而不是从当前作用域中可用的名称开始。

mod front_of_house {
 pub mod hosting {
 pub fn add_to_waitlist() {}
 }
}
use self::front_of_house::hosting;
pub fn eat_at_restaurant() {
 hosting::add_to_waitlist();
 hosting::add_to_waitlist();
 hosting::add_to_waitlist();
}

(1)、创建use路径时的惯用模式:

在使用关键字use指定函数路径时,只指定到函数的父模块,这意味着在调用函数时必须指定这个父模块,从而更清晰地表明当前函数有没有被定义在当前作用域,同样也能避免重复路径。

(2)、使用as关键字来提供新的名称:

使用use将同名类型引入作用域时所产生的问题还有另外一种解决办法:可以在路径后使用as关键字为类型指定一个新的本地名称,也就是别名。
示例:

use std::fmt::Result;
use std::io::Result as IoResult;
fn function1() -> Result {
 // --略
--
}
fn function2() -> IoResult<()> {
 // --略
--
}

(3)、使用pub usb重导出名称:

当我们使用use关键字将名称引入作用域时,这个名称会以私有的方式在新的作用域中生效。为了让外部代码能够访问到这些名称,可以通过组合使用pubuse实现。这项技术也被称作重导出。因为不仅将条目引入了作用域,而且使该条目可以被外部代码从新的作用域引入自己的作用域。

mod front_of_house {
	 pub mod hosting {
		 pub fn add_to_waitlist() {}
	 }
}
pub use crate::front_of_house::hosting;
pub fn eat_at_restaurant() {
	 hosting::add_to_waitlist();
	 hosting::add_to_waitlist();
	 hosting::add_to_waitlist();
}

(4)、使用嵌套的路径来清理众多use语句:

当想要使用同一个包或同一个模块内的多个条目时,将它们逐行列出会占据较多的纵向空间。可以在同一行内使用嵌套路径来将上述条目引入作用域。这一方法需要首先指定路径的相同部分,再在后面跟上两个冒号,接着用一对花括号包裹路径差异部分的列表。
示例:

use std::cmp::Ordering;
use std::io;
// ---略

可以写成:

use std::{cmp::Ordering, io};
// ---略

同理:

use std::io;
use std::io::Write;

可以写成:

use std::io::{self, Write};

(5)、通配符:

假如想要将所有定义在某个路径中的公共条目都导入作用域,那么可以在指定路径时在后面使用*通配符。
示例:

use std::collections::*;

上面这行use语句会将定义在std::collections内的所有公共条目都导入当前作用域。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Windows之XSshell7运行程序找不到mfc140u.dll解决方案

Xshell7依赖C库如下&#xff0c;下载如下2个x86&#xff08;32位&#xff09;运行库安装即可使用。 官网地址&#xff1a;《C运行库》

城市之星中山TOP3

城市之星中山TOP3 不断努力&#xff0c;突破自己。

《吐血整理》保姆级系列教程-玩转Fiddler抓包教程(5)-Fiddler监控面板详解

1.简介 按照从上往下&#xff0c;从左往右的计划&#xff0c;今天就轮到介绍和分享Fiddler的监控面板了。监控面板主要是一些辅助标签工具栏。有了这些就会让你的会话请求和响应时刻处监控中毫无隐私可言。监控面板是fiddler最核心的功能之一。记录了来自于服务器端&#xff0…

机器学习深度学习——softmax回归从零开始实现

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位即将上大四&#xff0c;正专攻机器学习的保研er &#x1f30c;上期文章&#xff1a;机器学习&&深度学习——向量求导问题 &#x1f4da;订阅专栏&#xff1a;机器学习&&深度学习 希望文章对你们有所帮助 …

39. Linux系统下在Qt5.9.9中搭建Android开发环境

1. 说明 QT版本:5.9.9 电脑系统:Linux JDK版本:openjdk-8-jdk SDK版本:r24.4.1 NDK版本:android-ndk-r14b 效果展示: 2. 具体步骤 大致安装的步骤如下:①安装Qt5.9.9,②安装jdk,③安装ndk,④安装sdk,⑤在qt中配置前面安装的环境路径 2.1 安装Qt5.9.9 首先下载…

国产化的接口测试、接口自动化测试工具Apipost的介绍及使用

Apipost介绍&#xff1a; Apipost是 API 文档、API 调试、API Mock、API 自动化测试一体化的研发协作赋能平台&#xff0c;它的定位 Postman Swagger Mock JMeter。 Apipost 是接口管理、开发、测试全流程集成工具&#xff0c;能支撑整个研发技术团队同平台工作&#xff0…

win10日程怎么同步到安卓手机?电脑日程同步到手机方法

在如今快节奏的生活中&#xff0c;高效地管理时间变得至关重要。而对于那些经常在电脑上安排日程的人来说&#xff0c;将这些重要的事务同步到手机上成为了一个迫切的需求。因为目前国内使用win10系统电脑、安卓手机的用户较多&#xff0c;所以越来越多的职场人士想要知道&…

手机怎么把word转换成pdf?这几种方法超简单

手机怎么把word转换成pdf&#xff1f;现在很多人在手机上处理文档&#xff0c;但是可能会遇到将Word文档转换为PDF的需求&#xff0c;以便更好地分享和传输文件。在下面这篇文章中&#xff0c;就给大家介绍几种将Word文档转换为PDF的方法。 方法一&#xff1a;使用迅捷PDF转换器…

spring复习:(55)注解配置的情况下@ComponentScan指定的包中的组件是怎么被注册到容器的?

配置类&#xff1a; 主类&#xff1a; 结论&#xff1a;是在context.refresh()处完成扫描和注册的。 fresh()的代码片段如下&#xff1a; 其中调用的invokeBeanFactoryPostProcessor代码如下&#xff1a; 其中调用的静态方法invokeBeanFactoryPostProcessors代码如下&#…

一些联动树形数据组装

export const pieselectdata [{entrustOrganization: 智慧法院电子诉讼平台,entrustOrganizationId: 161,productNames: [{batchCodes: [],productName: CL测试调解产品,},{batchCodes: [2022927_001,2022927_003,2022927_004,2022927_005,2022927_006,2022927_008,2022927_00…

文本预处理——文本数据增强

目录 文本数据增强回译数据增强法 文本数据增强 回译数据增强法

windows 系统安装sonarqube

SonarQube是一种自动代码审查工具&#xff0c;用于检测代码中的错误&#xff0c;漏洞和代码异味。它可以与您现有的工作流程集成&#xff0c;以便在项目分支和拉取请求之间进行连续的代码检查。 官方网站&#xff1a; https://www.sonarqube.org/ 1. 使用前提条件 运行SonarQ…

Excel双向柱状图的绘制

Excel双向柱状图在绘制增减比较的时候经常用到&#xff0c;叫法繁多&#xff0c;双向柱状图、上下柱状图、增减柱状图都有。 这里主要介绍一下Excel的基础绘制方法和复杂一点的双向柱状图的绘制 基础双向柱状图的绘制 首先升降的数据如下&#xff1a; 月份上升下降20220359-…

【二叉树】刷题(以递归写法为主)

226.翻转二叉树 101. 对称二叉树 104.二叉树的最大深度 111.二叉树的最小深度 222.完全二叉树的节点个数 110.平衡二叉树 102. 二叉树的所有路径 226.翻转二叉树 class Solution:def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:if not root:return…

13、PHP面向对象2(方法的访问控制、子类继承、常量)

1、类中的方法可以被定义为公有&#xff0c;私有或受保护。如果没有设置这些关键字&#xff0c;则该方法默认为公有。 public定义的方法&#xff0c;可以在类外使用。 protected定义的方法&#xff0c;只能在本类或子类的定义内使用。 private定义的方法&#xff0c;只能在本…

第八章 非编码RNA简介

第八章 非编码RNA简介 第一节 引言 第二节 长链非编码RNA简介 第三节 环形RNA简介 第四节 小RNA简介 4.1 miRNA 4.2 piRNA 4.3 小RNA数据分析

图像篡改及防篡改

有时候我们是攻击方&#xff0c;发送被网站或微信屏蔽的敏感图像&#xff0c;分享瓜时剔除可能暴露的个人信息&#xff0c;在平台分享其他平台的购物记录 有时候我们是防守方&#xff0c;判断他人给的图有没有造假嫌疑&#xff0c;判断是不是网图盗图 调研了图像造假的判别方案…

soft ip与hard ip

ip分soft和hard两种&#xff0c;soft就是纯代码&#xff0c;买过来要自己综合自己pr。hard ip如mem和analog与工艺有关。 mem的lib和lef是memory compiler产生的&#xff0c;基于bitcell&#xff0c;是foundry给的。 我正在「拾陆楼」和朋友们讨论有趣的话题&#xff0c;你⼀起…

C语言假期作业 DAY 03

目录 题目 一、选择题 1、已知函数的原型是&#xff1a; int fun(char b[10], int *a); &#xff0c;设定义&#xff1a; char c[10];int d; &#xff0c;正确的调用语句是&#xff08; &#xff09; 2、请问下列表达式哪些会被编译器禁止【多选】&#xff08; &#xff09; 3、…

Upload文件导入多条数据到输入框

需求场景&#xff1a;文本框内容支持批量导入(文件类型包括’.txt, .xls, .xlsx’)。使用AntD的Upload组件处理。 下面是Upload的配置&#xff08;伪代码&#xff09;&#xff0c;重点为beforeUpload中的逻辑 // Antd 中用到的Upload组件 import { UploadOutlined } from ant…