Rust之使用结构体来组织相关的数据

结构或结构体,是一种自定义数据类型,它允许我们命名多个相关的值并将它们组成一个有机的结合体。

1、定义并实例化结构体:

和元组一样,结构体中的数据可以拥有不同的类型,不同的是,结构体需要给每个数据赋予名字以便于清楚地表达它们的意义。

关键字struct被用来定义并命名结构体。一个良好的结构体名称应当能够反映出自身数据组合的意义。需要在随后的花括号中声明所有数据的名字及类型,这些数据也被称为字段。

示例:

rust 复制代码
struct User{
	username:String,
	email:String,
	sign_in_count:u64,
	active:bool,
}

在定义好结构体之后,需要为每个字段赋值来创建结构体实例,结构体实例赋值的顺序可以不按照所定义的顺序。

示例:

rust 复制代码
let User1 = User{
	email:String::from("xxxx@xx.com"),
	username:String::from("xxxx"),
	active:true,
	sign_in_count:1,
}

在创建好结构体实例之后,可以通过点号来访问实例中的特定的字段,例如需要访问User1中的名字,可以使用User1.username来获取。同样也可以通过点号来修改可变实例中相应的字段。

注:一旦实例可变,实例中所有的字段都是可变的,Rust不允许单独声明某一部分字段的可变性。

(1)、在变量名与字段名相同时使用简化版的字段初始化方法:

当函数的参数与结构体字段拥有完全一致的名称,可以使用名为字段初始化简写的语法来构建函数,这种语法并不会改变函数的行为。

示例:

rust 复制代码
fn build_user(email:String,username:String)->User{
	User{
		email,
		username,
		active:true,
		sign_in_count:1,
	}
}

(2)、使用结构体更新语法根据其他实例创建新实例:

许多新实例的创建,除了修改小部分的字段,其他部分与旧实例完全相同,就可以使用结构体更新语法来快速实现新实例的创建。

示例:

rust 复制代码
let User1 = User{
	email:String::from("xxxx@xx.com"),
	username:String::from("xxxx"),
	active:true,
	sign_in_count:1,
}
let User2 = User{
	email:String::from("xxxx@xx.com"),
	username:String::from("xxxx"),
	active:user1.active,
	sign_in_count:user1.sign_in_count,
}

为了简化代码量,可以使用更少的代码完成创建。

示例:

rust 复制代码
let User1 = User{
	email:String::from("xxxx@xx.com"),
	username:String::from("xxxx"),
	active:true,
	sign_in_count:1,
}
let User2 = User{
	email:String::from("xxxx@xx.com"),
	username:String::from("xxxx"),
	..user1
}

(3)、使用不需要对字段命名的元组结构来创建不同的类型:

元组结构体:使用一种类似于元组的方式来定义结构体。

元组结构体同样拥有用于表明自身含义的名称,但是无须在声明它时对其字段进行命名,仅保留字段的类型即可。当需要给元组赋予名字,并使其区别于其他拥有同样定义的元组时,可以使用元组结构体。

定义元组结构体时,依旧使用struct关键字开头,并由结构体名称及元组中的类型定义组成。

示例:

rust 复制代码
struct Color(i32,i32,i32);
struct Point(i32,i32,i32);

let black = Color(0,0,0);
let origin = Point(0,0,0);

(4)、没有任何字段的空结构体:

Rust允许创建没有任何字段的结构体。因为这种结构体与空元组十分相似,也被称为空结构体。当要在某些类型上实现一个trait,但是不需要该类型储存任何数据时,可以使用空结构体。

2、方法:

方法与函数十分相似:都是用fn关键字以及一个名称来进行声明;都可以拥有参数和返回值;都包含了一段在调试时执行的代码。但是方法和函数是两个不同的概念,因为方法总是被定义在某个结构体(或者枚举类型、trait对象)的上下文中,并且它们的第一个参数永远是self,用于指代调用该方法的结构体实例。

(1)、定义方法:

示例:

rust 复制代码
#[derive(Debug)]
struct Rectangle{
	width:u32,
	height:u32,
}
fn main(){
	let rect1 = Rectangle{width:30,height:50};
	println!("rect1 is {:?}",rect1);
	println!("The area of the rectangle is {} square pixels.",area(&rect1));
}
fn area(rectangle:&Rectangle) -> u32{
	rectangle.width*rectangle.height
}

使用方法进行改写:

rust 复制代码
#[derive(Debug)]
struct Rectangle{
	width:u32,
	height:u32,
}
impl Rectangle{
	fn area(&self) -> u32 {
		self.width*self.height
	}
}
fn main(){
	let rect1 = Rectangle{width:30,height:50};
	println!("rect1 is {:?}",rect1);
	println!("The area of the rectangle is {} square pixels.",rect1.area());
}

为了在Rectangle的上下文环境中定义这个函数,需要将area函数移动到一个由impl关键字起始的代码块中,并把签名中的第一个参数和函数中使用该参数的地方改写成self。此外,还需要把main函数中调用area函数的地方,用方法调用的语法进行改写。方法调用是通过在实例后面加上点号,并跟上方法名、括号及可能的参数来实现的。

(2)、关联函数:

除了方法外,Rust还允许定义不用接收self作为参数的函数。由于这类函数与结构体相互关联,故称之为关联函数。

关联函数常常被用作构造器来返回一个结构体的新实例。例如,可以编写一个接收一维参数的关联函数,它会将输入的参数同时作用长度与宽度来构造正方形的Rectangle实例。

示例:

rust 复制代码
impl Rectangle{
	fn square(size:u32) -> Rectangle{
		Rectangle{width:size,height:size}
	}
}

在类型名称后面添加::来调用关联函数,例如let sq = Rectangle::square(3);

相关推荐
liulilittle2 分钟前
moodycamel::ConcurrentQueue 清空队列的方法论
开发语言·c++
shoubepatien4 分钟前
JAVA -- 09
java·开发语言
郑州光合科技余经理17 分钟前
海外国际版同城服务系统开发:PHP技术栈
java·大数据·开发语言·前端·人工智能·架构·php
Yorelee.19 分钟前
ms-swift在训练时遇到的部分问题及解决方案
开发语言·nlp·transformer·swift
行走的bug...22 分钟前
python项目管理
开发语言·python
appearappear27 分钟前
Mac 上重新安装了Cursor 2.2.30,重新配置 springboot 过程记录
java·spring boot·后端
CryptoRzz36 分钟前
日本股票 API 对接实战指南(实时行情与 IPO 专题)
java·开发语言·python·区块链·maven
yugi98783837 分钟前
基于M序列的直扩信号扩频码生成方法及周期长码直扩信号的MATLAB实现方案
开发语言·matlab
谷哥的小弟43 分钟前
Spring Framework源码解析——RequestContext
java·后端·spring·框架·源码
乾元44 分钟前
基于时序数据的异常预测——短期容量与拥塞的提前感知
运维·开发语言·网络·人工智能·python·自动化·运维开发