Rust struct
struct 结构体
自定义的数据类型,为相关联的值命名,打包成有意义的组合。
类似python的dict,但是赋值的时候可以不按顺序。初始化的时候一定要全部赋值完,不能缺少。先要创建结构体,再实例化结构体。
取值时使用点标记法。修改结构体里的值必须要求结构体是可变的 mut。一旦struct的实例是可变的,那么实例中的所有字段都是可变的。
fn main(){
struct User{
username: String,
email: String,
password: u64,
}
let mut achu = User{
// 可以不按顺序赋值,但是不能缺字段
email: String::from("achu@achu.com"),
username: String::from("achu"),
password: 123,
};
}
字段初始化简写
当字段名和字段值对应的变量相同时,就可以使用字段初始化简写的方式。
struct 可以作为函数的返回值。
struct User{
username: String,
email: String,
password: u64,
}
// User可以作为单独一种类型返回,因为它是结构体
fn makeUser(email: String, username: String) -> User{
// 这里接收的值和struct里的值是一样的。
User {
email,
username,
password: 123
}
}
struct 更新
基于某个struct实例来创建一个新的实例的时候,可以使用struct更新语法。
有相同的值时
fn main(){
struct User{
username: String,
email: String,
password: u64,
}
let mut achu = User{
// 可以不按顺序赋值,但是不能缺字段
email: String::from("achu@achu.com"),
username: String::from("achu"),
password: 123,
};
let mut afeng = User{
email: String::from("afeng@achu.com"),
username: String::from("afeng"),
// password: achu.password, 等价于: ..achu
..achu
};
println!("{}", achu.email);
}
tuple struct
tuple struct 整体有个名,但是里面的元素没有名字。适用于整个tuple起名,并让它不同于其他的tuple,而且又不需要给每个元素起名。
struct Color(i32, i32, i32);
let black = Color(0, 0, 0);
unit-Like Struct 空结构体
定义没有任何字段的结构体,适用于需要在某个类型上实现某个trait,但是在里面又没有想要的存储的数据。
struct 数据的所有权
- struct实例是有效的,那么里面的字段数据也是有效的。
- struct可以存放应用,需要生命周期。不用就会报错。
结构体必须掌握字段值所有权,因为结构体失效的时候会释放所有字段。
结构体没有实现std::fmt::Display方法,结构体有不确定性,所以不能直接println!("{}")。
解决方法:使用println!("{:?}")或者println!("{:#?}"),但是要加debug模式(类似装饰器)#[derive(Debug)]
fn main() {
#[derive(Debug)]
struct User{
username: String,
email: String,
password: u64,
}
let mut achu = User{
// 可以不按顺序赋值,但是不能缺字段
email: String::from("achu@achu.com"),
username: String::from("achu"),
password: 123,
};
println!("{:?}", achu);
// 更加方便看,加个#
println!("{:#?}", achu);
}
struct 方法
可以把struct看做一个类,而方法就是这个类中的方法(类似python)
方法和函数类似:fn关键字,名称,参数和返回值。
方法和函数的区别:
- 方法是在struct,enum或trait对象的上下文中定义的。
- 第一个参数是self, 标识方法被调用的struct的实例。
方法的self可以是可变的。也可以获得其所有权或可变借用,和其他参数一样。
// impl structName
impl User {
fn makeUserZero(userModule: &User) -> u64{
println!("user create success!");
userModule.password
}
// 实例本身是第一个参数,所以self也不用手动传
fn makeUserOne(&self) -> u64 {
println!("user create success!");
self.password
}
}
关联函数
不把self作为第一个参数的函数,叫做关联函数(不是方法,但是与这个类型由关联)。类似python的类静态方法。
- eg: String::from()
关联函数通常用于构造器。也就是创造被关联类型的一个实例。
调用的方法是::,两个冒号
可以创造多个impl块
方法传参
当一个实例化的结构体对象调用它的结构体方法时,可以传入另外一个结构体对象。
在调用方法时:rust根据情况自动添加&、&mut或*,以便object可以匹配方法的签名。
p1.dispatch(&p2);
(&p1).dispatch(&p2);
这两行代码是一样的。