一、自定义类型
自定义数据类型主要有:结构体、枚举
- 结构体:通过struct关键字创建。
- 枚举:通过enum关键字创建。
1.1 结构体
结构体与元组类似,也可以把多个类型组合到一起,作为新的类型。区别在于,它的每个元素都有自己的名字。
结构体中每个元素之间采用逗号分开,最后一个逗号可以省略不写。类型跟在冒号后面,但是不能使用自动类型推导功能,必须显式指定。结构体类型的初始化语法类似于json的语法,使用“成员–冒号–值”的格式。如果有局部变量名字和成员变量名字恰好一致,那么可以省略掉重复的冒号初始化,这是一种简化的写法。
结构体有三种类型:普通结构体、元组结构体、单元结构体
- 普通结构体:与经典的C语言风格结构体类似。
- 元组结构体:事实上就是具名元组而已。它就像是元组和结构体的混合。区别在于,元组结构体有名字,而它的成员没有名字。
- 单元结构体:不带字段的结构体。
以下是简单的样例:
#[derive(Debug)]
struct Person {
name: String,
age: u8,
}
//单元结构体
struct Unit;
//元组结构体
struct Pair(i32, f32);
//普通结构体
struct Point {
x: f32,
y: f32,
}
//结构体可以作为另一个结构体的字段
#[allow(dead_code)]
struct Rectangle {
top_left: Point,
bottom_right: Point,
}
fn main() {
//局部变量名字和成员变量名字恰好一致,使用简化写法
let name = String::from("Peter");
let age = 27;
let peter = Person { name, age };
//使用了Debug属性的结构体,可以用Debug方式打印结构体
println!("{:?}", peter);
//实例化结构体Point
let point: Point = Point { x: 10.3, y: 0.4 };
//访问point的字段
println!("point coordinates: ({}, {})", point.x, point.y);
//使用结构体更新语法创建新的point,
//这样可以用到之前的point的字段
let bottom_right = Point { x: 5.2, ..point };
//bottom_right.y与point.y一样,因为这个字段就是从point中来的
println!("second point: ({}, {})", bottom_right.x, bottom_right.y);
//使用let绑定来解构point
let Point {
x: left_edge,
y: top_edge,
} = point;
let _rectangle = Rectangle {
//结构体的实例化也是一个表达式
top_left: Point {
x: left_edge,
y: top_edge,
},
bottom_right: bottom_right,
};
//实例化一个单元结构体
let _unit = Unit;
//实例化一个元组结构体
let pair = Pair(1, 0.1);
//访问元组结构体的字段
println!("pair contains {} and {}", pair.0, pair.1);
//解构一个元组结构体
let Pair(integer, decimal) = pair;
println!("pair contains {} and {}", integer, decimal);
}
1.2 枚举
枚举类型允许创建一个从数个不同取值中选其一。Rust枚举类型也可以像C语言风格的枚举类型那样使用。与C/C++中的枚举相比,Rust中的枚举要强大得多,它可以为每个成员指定附属的类型信息。枚举中的每个元素的定义语法与结构体的定义语法类似,任何一个在 结构体中合法的取值在枚举中也合法。
枚举和结构体为内部成员创建了新的名字空间。如果要访问内部成员,可以使用::符号。因此,不同的枚举中重名的元素也不会互相冲突。
在没有重名的元素的情况下,使用use声明,就可以不写出名称的完整路径了,但是如果存在重名的元素,则需要名称的完整路径。
以下是简单的样例:
//该属性用于隐藏对未使用代码的警告。
#![allow(dead_code)]
enum Status {
Rich,
Poor,
}
enum Work {
Civilian,
Soldier,
}
//C语言风格枚举,拥有隐式辨别值,从0开始的
enum Number {
Zero,
One,
Two,
}
//C语言风格枚举,拥有显式辨别值
enum Color {
Red = 0xff0000,
Green = 0x00ff00,
Blue = 0x0000ff,
}
fn main() {
//显式地use各个名称使他们直接可用,而不需要指定它们来自Status
use Status::{Poor, Rich};
//自动地use Work内部的各个名称
use Work::*;
//Poor等价于Status::Poor
let status = Poor;
//Civilian等价于Work::Civilian
let work = Civilian;
//使用模式匹配
match status {
//没有用完整路径,因为上面显式地使用了use
Rich => println!("The rich have lots of money!"),
Poor => println!("The poor have no money..."),
}
//使用模式匹配
match work {
//没有用完整路径,因为上面显式地使用了use
Civilian => println!("Civilians work!"),
Soldier => println!("Soldiers fight!"),
}
//枚举成员值可以转成整型
println!("zero is {}", Number::Zero as i32);
println!("one is {}", Number::One as i32);
println!("roses are #{:06x}", Color::Red as i32);
println!("violets are #{:06x}", Color::Blue as i32);
}