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

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

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

和元组一样,结构体中的数据可以拥有不同的类型,不同的是,结构体需要给每个数据赋予名字以便于清楚地表达它们的意义。
关键字struct被用来定义并命名结构体。一个良好的结构体名称应当能够反映出自身数据组合的意义。需要在随后的花括号中声明所有数据的名字及类型,这些数据也被称为字段。
示例:

struct User{
	username:String,
	email:String,
	sign_in_count:u64,
	active:bool,
}

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

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

在创建好结构体实例之后,可以通过点号来访问实例中的特定的字段,例如需要访问User1中的名字,可以使用User1.username来获取。同样也可以通过点号来修改可变实例中相应的字段。
注:一旦实例可变,实例中所有的字段都是可变的,Rust不允许单独声明某一部分字段的可变性。

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

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

fn build_user(email:String,username:String)->User{
	User{
		email,
		username,
		active:true,
		sign_in_count:1,
	}
}

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

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

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,
}

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

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关键字开头,并由结构体名称及元组中的类型定义组成。
示例:

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)、定义方法:

示例:

#[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
}

使用方法进行改写:

#[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实例。
示例:

impl Rectangle{
	fn square(size:u32) -> Rectangle{
		Rectangle{width:size,height:size}
	}
}

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值