Rust语言入门教程(九) - 结构体

格式及语法

在其他很多编程语言中,有类(Class)的存在,在Rust中,我们没有类(Class)的概念,我们使用结构体(Struct)。

与一个结构体相关的有以下几个部分:

  • 数据字段
  • 方法
  • 关联函数

声明一个结构体及其字段的格式如下:

rust 复制代码
pub struct RedFox {
	enemy: bool,
	life: u8,
}

struct关键词开头,后面紧跟结构体的名称(以大写字母开头的驼峰式命名),大括号中是结构体的数据字段,每个字段由字段名称及它的类型声明组成, 字段间用,分隔。

最后一个字段后面也可以加上,, 并且我们推荐大家这样做,以防在以后添加新字段时忘记在前面的字段后添加,

正如我们在前面的章节中提到的, Rust中的函数默认都是私有的,结构体也是一样, 如果想在别的模块中使用结构体,需要加上pub标识:

rust 复制代码
pub struct RedFox {
	enemy: bool,
	life: u8,
}

结构体的字段默认也是私有的,默认只能在结构体被定义的模块内被访问, 如果想在结构体被定义的模块之外访问结构体的字段,则需要将该字段也标识成pub:

rust 复制代码
pub struct RedFox {
	pub enemy: bool,
	life: u8,
}

结构体的数据字段本身也可以是一个结构体:

rust 复制代码
pub struct RedFox {
	enemy: bool,
	life: u8,
	profile: Profile,
}

struct Profile {
	name: String,
	age: u8,
}

结构体关联函数与方法

实例化一个结构体时,我们需要为这个结构体的每个字段都指定一个值。 一般来说,我们会为结构体实现一个关联函数,作为结构体的构造函数来创建一个具有默认值的结构体实例:

rust 复制代码
struct RedFox {
	enemy: bool,
	life: u8,
}

impl RedFox {
	fn new() -> Self {
		Self {
			enemy: true,
			life: 70,
		}
	}
}

结构体的方法和关联函数在一个叫impl的代码块中实现,与结构体的定义是不同的代码块。这个代码块以impl开头, 后面紧跟结构体的名称, 然后在其后的大括号中, 实现结构体的方法和关联函数。

上述代码中的fn new() -> Self被称为结构体的关联函数,因为它没有使用self&self作为其第一个参数。 这样的函数在一些其他语言(如Python)中被称为类方法,可以直接通过类名而不是类的实例调用。

在Rust中, new函数是我们约定俗成的一个关联函数,用于创建一个具有默认值的结构体实例。在结构体的方法或关联函数中, 首字母大写的Self等价于结构体的名称本身, 因此上面的关联函数也可以这样写:

rust 复制代码
impl RedFox {
	fn new() -> RedFox {
		RedFox {
			enemy: true,
			life: 70,
		}
	}
}

但我们更推荐使用Self

结构体方法也是在impl代码块中进行实现的, 与关联函数不同的是,结构体方法总是以self&self&mut self作为第一个参数。

rust 复制代码
impl RedFox {
	// 关联函数
	fn function() ...
	// 方法
	fn move(self) ...
	fn borrow(&self) ...
	fn mut_borrow(&mut self) ...
}

关联函数可以直接通过结构体名称调用, 而方法只能通过结构体的示例调用。

实例化结构体

rust 复制代码
let fox = RedFox::new();

上面的代码会创建一个具有默认值的RedFox结构体。注意Rust中的作用域操作符是::, 我们使用它来访问类似命名空间中的部分内容。例如在前面的章节中, 我们在use语句中也使用了::来访问模块中的函数。在这个例子中,我们则是使用::来访问一个结构体的关联函数。

一旦我们有了一个实例,我们就能像在大多数语言一样,通过这个实例,使用.操作符来获取或设置特定字段的值,或者调用方法。

rust 复制代码
let fox = RedFox::new();
let life_left = fox.life;
fox.enemy = false;
fox.some_method();

小结

本章我们介绍了Rust中的结构体的定义及其关联函数与方法的使用,下一章将介绍Rust中另一个非常重要的概念, Trait。

相关推荐
葫芦和十三6 小时前
图解 MongoDB 09|explain 再读:从 queryPlanner 到 executionStats
后端·mongodb·agent
葫芦和十三7 小时前
图解 MongoDB 10|覆盖查询:让索引把活干完,根本不用回表
后端·mongodb·agent
大鸡腿同学8 小时前
从 CoT 思维链到 ReAct:智能 Agent 到底是怎么 “思考” 的?
后端
IT_陈寒10 小时前
Vite的静态资源打包让我熬夜到三点,这坑千万别跳
前端·人工智能·后端
SamDeepThinking11 小时前
高并发场景下,CompletableFuture与ForkJoinPool该如何取舍?
java·后端·面试
Asize11 小时前
多模态生图:从 Vite 工程化到前端调用 Qwen Image
javascript·人工智能·后端
java小白小11 小时前
SpringBoot(09):缓存实战——穿透、雪崩、击穿的解决方案
后端
java小白小11 小时前
SpringBoot(08):Redis 集成——5 分钟给你的项目加上缓存
后端
LiuMingXin12 小时前
意图与代码之间:AI编程范式全景解读
前端·后端·面试
用户342323237631712 小时前
边缘计算与云边协同——当采集不再只是“上传“
后端