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);

相关推荐
Envyᥫᩣ2 分钟前
C#语言:从入门到精通
开发语言·c#
齐 飞10 分钟前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb
童先生23 分钟前
Go 项目中实现类似 Java Shiro 的权限控制中间件?
开发语言·go
lulu_gh_yu24 分钟前
数据结构之排序补充
c语言·开发语言·数据结构·c++·学习·算法·排序算法
LunarCod27 分钟前
WorkFlow源码剖析——Communicator之TCPServer(中)
后端·workflow·c/c++·网络框架·源码剖析·高性能高并发
Re.不晚1 小时前
Java入门15——抽象类
java·开发语言·学习·算法·intellij-idea
老秦包你会1 小时前
Qt第三课 ----------容器类控件
开发语言·qt
凤枭香1 小时前
Python OpenCV 傅里叶变换
开发语言·图像处理·python·opencv
ULTRA??1 小时前
C加加中的结构化绑定(解包,折叠展开)
开发语言·c++
码农派大星。1 小时前
Spring Boot 配置文件
java·spring boot·后端