定义并实例化 struct
struct 中文名称是 结构体,可以自定义数据类型,为相关联的值命名,并打包成有意义的组合
定义 struct
- 使用
struct 关键字,并为整个 struct 命名
- 在花括号内,为所有字段(Field)定义名称与类型
1 2 3 4 5 6
| struct User { username: String, email: String, sign_in_count: u64, active: bool, }
|
实例化 struct
- 想要使用 struct,需要创建 struct 的实例
1 2 3 4 5 6
| let user1 = User{ email: String::from("some@example.com"), usernmae: String::from("someusernmae123"), active: true, sign_in_count: 1, };
|
取得 struct 里面某个值
为 user 的某个字段赋予新值,需要在实例化时为 user 加上 mut 关键字,然后使用点标记就可以赋值
一旦 struct 的实例是可变的,那么实例中所有的字段都是可变的
1 2 3 4 5 6 7 8
| let mut user1 = User{ email: String::from("some@example.com"), usernmae: String::from("someusernmae123"), active: true, sign_in_count: 1, };
user1.email = String::from("anotheremail@example.com");
|
struct 作为函数的返回值
1 2 3 4 5 6 7 8
| fn build_user(email: String, username: String) -> User { User{ email: email, usernmae: username, active: true, sign_in_count: 1, } }
|
字段初始化简写
- 当字段名与字段值对应变量相同时,就可以使用该字段初始化简写方式
1 2 3 4 5 6 7 8
| fn build_user(email: String, usernmae: String) -> User { User{ email, username, active: true, sign_in_count: 1, } }
|
struct 更新语法
- 当你基于某个 struct 实例来创建一个新实例的时候,可以使用 struct 更新语法
不使用更新语法
1 2 3 4 5 6
| let user2 = User{ email: String::from("another@axmple.com"), username: String::from("anotherusername567"), active: user1.active, sign_in_count: user1.sign_in_count, };
|
使用更新语法
1 2 3 4 5
| let user2 = User { email: String::from("another@axmple.com"), username: String::from("anotherusername567"), ..user1 };
|
Tuple struct
- 可定义类似 tuple 的 struct,叫做 tuple struct
- tuple struct 整体有个名,但里面的元素没有名
- 适用:想给整个 tuple 起名,并让它不同于其它 tuple,而且又不需要给每个元素起名
- 定义 tuple struct: 使用 struct 关键字,后面是名字,以及里面元素的类型
black 和 origin 是不同的类型,是不同 tuple struct 的实例
1 2 3 4
| struct Color(i32, i32, i32); struct Point(i32, i32, i32); let black = Color(0, 0, 0); let orign = Ponit(0, 0, 0);
|
Unit-Like Struct(没有任何字段)
- 可以定义没有任何字段的 struct,叫做 Unit-Like struct(因为与(), 单元类型类似)
- 适用于需要在某个类型上实现某个 trait,但是在里面又没有想要存储的数据
struct 数据的所有权
1 2 3 4 5 6
| struct User{ username: String, email: String, sign_in_count: u64, active: bool, }
|
struct 例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #[derive(Debug)] struct Rectangle { width: u32, length: u32, }
fn main() { let rect = Rectangle { width: 30, length: 50 };
println!("{}", area(&rect)); println!("{:#?}", rect); }
fn area(rect: &Rectangle) -> u32 { rect.width * rect.length }
|
struct 方法
- 方法和函数类似:
fn 关键字、名称、参数、返回值
- 方法与函数不同之处
- 方法是在struct(或
enum、trait对象)的上下文中定义
- 第一个参数是 self,表示方法被调用的 struct 实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #[derive(Debug)] struct Rectangle { width: u32, length: u32, }
impl Rectangle { fn area(&self) -> u32 { self.width * self.length } }
fn main() { let rect = Rectangle { width: 30, length: 50 };
println!("{}", rect.area()); println!("{:#?}", rect); }
|
- 在
impl 块里定义方法
- 方法的第一个参数可以是 &self,也可以获得其所有权或可变借用(
&mut self),和其他参数一样
方法调用的运算符
- C/C++:object->something() 和 (*object).something() 一样
- Rust 没有
-> 运算符
- Rust 会自动引用和解引用
- 在调用方法时,Rust 根据情况自动添加 &、
&mut 或 *,以便 object 可以匹配方法的签名
- 下面两行代码效果相同
p1.distance(&2);
(&p1).distance(&p2)
方法参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| #[derive(Debug)] struct Rectangle { width: u32, length: u32, }
impl Rectangle { fn area(&self) -> u32 { self.width * self.length }
fn can_hold(&self, other: &Rectangle) -> bool { self.width > other.width && self.length > other.length } }
fn main() { let rect1 = Rectangle { width: 30, length: 50, }; let rect2 = Rectangle { width: 10, length: 40, }; let rect3 = Rectangle { width: 35, length: 55, };
println!("{}", rect1.can_hold(&rect2)); println!("{}", rect1.can_hold(&rect3)); }
|
关联函数
- 可以在
impl 快里定义不把 self 作为第一个参数的函数,他们叫关联函数(并不是方法)
- 关联函数通常用于构造器
::符号
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #[derive(Debug)] struct Rectangle { width: u32, length: u32, }
impl Rectangle { fn area(&self) -> u32 { self.width * self.length }
fn can_hold(&self, other: &Rectangle) -> bool { self.width > other.width && self.length > other.length }
fn square(size: u32) -> Rectangle { Rectangle { width: size, length: size, } } }
fn main() { let s = Rectangle::square(20); println!("{:#?}", s); }
|
多个 impl 块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| #[derive(Debug)] struct Rectangle { width: u32, length: u32, }
impl Rectangle { fn area(&self) -> u32 { self.width * self.length } }
impl Rectangle { fn can_hold(&self, other: &Rectangle) -> bool { self.width > other.width && self.length > other.length } }
impl Rectangle { fn square(size: u32) -> Rectangle { Rectangle { width: size, length: size, } } }
fn main() { let s = Rectangle::square(20); println!("{:#?}", s); }
|