Rust中的自定义类型:
结构体 | 枚举 | 常量 |
---|---|---|
static | enum | const/static |
结构体
- 掌握结构体的解构,掌握结构体的嵌套。
- 例题:1.计算Rectangle面积的函数rect_area
- 2.返回长方形
struct Point {
x: f32,
y: f32,
}
struct Rectangle {
top_left: Point,
bottom_right: Point,
}
impl Rectangle {
fn rect_area(&self) -> f32 {
let Rectangle {
top_left: Point { x: x1, y: y1 },
bottom_right: Point { x: x2, y: y2 },
} = self;
(x1 - x2).abs() * (y1 - y2).abs()
}
fn square(topleft: Point, length: f32) -> Rectangle {
Rectangle {
bottom_right: Point {
x: topleft.x + length,
y: topleft.y - length,
},
top_left: topleft,
}
}
}
fn main() {
let rectangle = Rectangle {
top_left: Point { x: 10.0, y: 9.0 },
bottom_right: Point { x: 12.0, y: 11.0 },
};
println!("{}", rectangle.rect_area());
let top = Point { x: 9.3, y: 3.4 };
let new_rect = Rectangle::square(top, 4.5);
println!("{}", new_rect.rect_area());
}
枚举
- 在struct中合法的取值在enum中也合法。
- 熟练使用
use
和match
简化你的enum
。 - 使用use则不需要显式声明,仅使用*即可。
- 常用enum創建鏈表。
- 使用枚举的情况是在需要进行分类的时候进行,如果觉得名字太常,可以使用类型别名:
enum VeryVerboseEnumOfThingsToDoWithNumbers {
Add,
Subtract,
}
// 创建一个类型别名
type Operations = VeryVerboseEnumOfThingsToDoWithNumbers;
fn main() {
// 我们可以通过别名引用每个枚举变量,避免使用又长又不方便的枚举名字
let x = Operations::Add;
}
- 或者是在impl方法或者函数块中使用
self
别名:
enum VeryVerboseEnumOfThingsToDoWithNumbers {
Add,
Subtract,
}
impl VeryVerboseEnumOfThingsToDoWithNumbers {
fn run(&self, x: i32, y: i32) -> i32 {
match self {
Self::Add => x + y,
Self::Subtract => x - y,
}
}
}
- C语言风格使用方法:
// 该属性用于隐藏对未使用代码的警告。
#![allow(dead_code)]
// 拥有隐式辨别值(implicit discriminator,从 0 开始)的 enum
enum Number {
Zero,
One,
Two,
}
// 拥有显式辨别值(explicit discriminator)的 enum
enum Color {
Red = 0xff0000,
Green = 0x00ff00,
Blue = 0x0000ff,
}
fn main() {
// `enum` 可以转成整型。
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);
}
- 测试实例:链表
- 注意其中的ref引用的作用,不要将其与Ref指针搞混。
use List::*;
enum List {
// Cons:元组结构体,包含链表的一个元素和一个指向下一节点的指针
Cons(u32, Box<List>),
// Nil:末结点,表明链表结束
Nil,
}
// 可以为 enum 定义方法
impl List {
// 创建一个空的 List 实例
fn new() -> List {
// `Nil` 为 `List` 类型(译注:因 `Nil` 的完整名称是 `List::Nil`)
Nil
}
// 处理一个 List,在其头部插入新元素,并返回该 List
fn prepend(self, elem: u32) -> List {
// `Cons` 同样为 List 类型
Cons(elem, Box::new(self))
}
// 返回 List 的长度
fn len(&self) -> u32 {
// 必须对 `self` 进行匹配(match),因为这个方法的行为取决于 `self` 的
// 取值种类。
// `self` 为 `&List` 类型,`*self` 为 `List` 类型,匹配一个具体的 `T`
// 类型要好过匹配引用 `&T`。
match *self {
// 不能得到 tail 的所有权,因为 `self` 是借用的;
// 因此使用一个对 tail 的引用
Cons(_, ref tail) => 1 + tail.len(),
// (递归的)基准情形(base case):一个长度为 0 的空列表
Nil => 0
}
}
// 返回列表的字符串表示(该字符串是堆分配的)
fn stringify(&self) -> String {
match *self {
Cons(head, ref tail) => {
// `format!` 和 `print!` 类似,但返回的是一个堆分配的字符串,
// 而不是打印结果到控制台上
format!("{}, {}", head, tail.stringify())
},
Nil => {
format!("Nil")
},
}
}
}
fn main() {
// 创建一个空链表
let mut list = List::new();
// 追加一些元素
list = list.prepend(1);
list = list.prepend(2);
list = list.prepend(3);
// 显示链表的最后状态
println!("linked list has length: {}", list.len());
println!("{}", list.stringify());
}
常量
- 常量分为两种,一种是生命周期标注
'static
,一种是const
,不可改变量。 - "string"字面量(一种切片,类型为
&str
)可以不经改动被赋予static变量,&'static str
就包含了所要求的生命周期'static
。其他的引用类型都 必须特地声明,使之拥有'static
生命周期。