定义并实例化Struct
什么是 struct
- struct,结构体
- 自定义的数据类型
- 为相关联的值命名,打包 => 有意义的组合
定义 struct
- 使用 struct 关键字,并为整个 struct 命名
- 在花括号内,为所有字段 (Field) 定义名称和类型
struct User{
username:String,
email:String,
sign_in_count:u64,
active:bool,
}
实例化 struct
- 想要使用 struct,需要创建 struct 的实例
- 为每个字段指定具体值
- 无需按声明的顺序进行指定
let user1=User{
username:String::from("huihui"),
email:String::from("[email protected]"),
active:true,
sign_in_count:1,
};
取得 struct 里面的某个值
- 使用点标记法:
user1.email=String::from("xiaohuihui");
- 一旦 struct 的实例是可变的,那么实例中所有的字段都是可变的
- struct可以作为函数的返回值
字段初始化简写
- 当字段名与字段值对应变量名相同时,就可以使用字段初始化简写的方式:
fn build_user(email:String,username:String)->User {
User {
username,
email,
sign_in_count: 1,
active: true
}
}
struct 更新语法
- 当你想基于某个 struct 实例来创建一个新实例的时候,可以使用 struct 更新语法:
let user2=User{
email:String::from("[email protected]"),
username:String::from("huihui2"),
..user1
};
Tuple struct
- 可定义类似 tuple 的 struct,叫做 tuple struct
- Tuple struct 整体有个名,但里面的元素没有名
- 适用:想给整个 tuple 起名,并让它不同于其它 tuple,而且又不需要给每个元素起名
- 定义 tuple struct: 使用 struct 关键字,后边是名字,以及里面元素的类型
struct color(i32,i32,i32);
struct point(i32,i32,i32);
let back=color(0,0,0);
let origin=point(0,0,0)
- black 和 origin 是不同的类型,是不同 tuple struct 的实例。
Unit-Like Struct (没有任何字段)
- 可以定义没有任何字段的 struct,叫做 Unit-Like struct(因为与0,单元类型类似)
- 适用于需要在某个类型上实现某个 trcit,但是在里面又没有想要存储的数据
struct 数据的所有权
- 上面user例子
- 这里的字段使用了 string 而不是 &str:
- 该struct 实例拥有其所有的数据
- 只要 struct 实例是有效的,那么里面的字段数据也是有效的
- struct 里也可以存放引用,但这需要使用生命周期(以后讲)
- 生命周期保证只要 struct 实例是有效的,那么里面的引用也是有效的。
- 如果 struct 里面存储引用,而不使用生命周期,就会报错(例子)。
struct 的方法
- 方法和函数类似:fn 关键字、名称、参数、返回值
- 方法与函数不同之处:
- 方法是在 struct(或 enum、trai 对象)的上下文中定义
- 第一个参数是 self,表示方法被调用的 struct 实例
定义方法
- 在impl块里定义方法
- 方法的第一个参数可以是 &self,也可以获得其所有权 或 可变借用。和其他参数一样。
- 更良好的代码组织
struct Rectangle{
width:u32,
length:u32
}
impl Rectangle {
fn area(&self) {
self.width * self.length
}
}
方法调用的运算符
- C/C++: object->something()和(*object).something()一样
- Rust 没有 -> 运算符
- Rust 会自动引用或解引用
- 在调用方法时就会发生这种行为
- 在调用方法时,Rust 根据情况自动添加 &、&mut 或*,以便 object 可以匹配方法的签名。
- 下面两行代码效果相同:
- p1.distance(&p2);
- (&p1).distance(&p2);
关联函数
- 可以在 impl 块里定义不把 self 作为第一个参数的函数,它们叫关联函数 (不是方法)
-例如: String::from() - 关联函数通常用于构造器
- ::符号
- 关联函数
- 模块创建的命名空间
impl Rectangle {
fn square(size:u32)->Rectangle {
Rectangle { width: size, length: size }
}
}
fn main() {
let s=Rectangle::square(10);
}
多个impl块
- 每个 struct 允许拥有多个 impl块