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

相关推荐
湫ccc9 分钟前
《Python基础》之pip换国内镜像源
开发语言·python·pip
瓜牛_gn10 分钟前
依赖注入注解
java·后端·spring
fhvyxyci10 分钟前
【C++之STL】摸清 string 的模拟实现(下)
开发语言·c++·string
qq_4597300312 分钟前
C 语言面向对象
c语言·开发语言
菜鸟学Python21 分钟前
Python 数据分析核心库大全!
开发语言·python·数据挖掘·数据分析
Estar.Lee27 分钟前
时间操作[取当前北京时间]免费API接口教程
android·网络·后端·网络协议·tcp/ip
喜欢猪猪29 分钟前
Django:从入门到精通
后端·python·django
一个小坑货29 分钟前
Cargo Rust 的包管理器
开发语言·后端·rust
bluebonnet2733 分钟前
【Rust练习】22.HashMap
开发语言·后端·rust
古月居GYH33 分钟前
在C++上实现反射用法
java·开发语言·c++