结构体
怎么说呢?
结构体 struct 就是自定义的一种数据类型,里面存储着各种名称的、不同类型的数据(字段 field)。
在结构体中存储引用需要生命周期,这个东西后面(可能是几个月后)会讲
普通结构体的定义和实例化
struct User { // struct 要定义在 main 外 // struct name_of_struct_名称 {}
email: String, // name: type, 名称: 类型,
username: String,
nickname: String,
groups: Vec<String>,
password: String,
userid: i64,
is_online: bool, // 每个字段后都要有 ,
} // 结尾没有分号
fn main() {
// 实例化
let mut panjk0518 = User { // let (mut) name = struct_name { field: value, ... };
email: String::from("someone@somedomain.com"), // 每个字段后都要有 ,
username: String::from("panjk0518"),
nickname: String::from("panjk0518"),
groups: vec![String::from("公测用户"),],
password: String::from("5L2g56uf54S25Y+R546w5LqG6L+Z5pivIGJhc2U2NO+8geS4jei/h+WvhueggeaYr+S4jeWPr+iDveWRiuivieS9oOeahO+8gQ=="), // 你猜这是啥?
userid: 123456, // 真的 id 我不知道
is_online: true,
}; // 结尾有分号
let email = String::from("another_person@somedomain.com");
let user2 = User {
email, // 如果你的变量和字段同名,可以直接写变量名
..panjk0518 // ..另一实例 代表其它内容和另一实例相同
};
}
元组结构体和类单元结构体
引用 Rust 官方文档。
元组结构体
看着可能没啥用,但是等到学运算符重载和自定义输出就有用了,它可以区分于正常元组,实现一些自定义操作。
其实就是普通结构体去掉字段名。
struct Color(i32, i32, i32); // struct name_of_tuple_struct结构体名称(元组数据类型1, 2, 3, ...);(有分号!)
struct Point(i32, i32, i32);
fn main() {
let black = Color(0, 0, 0); // 实例化:let (mut) variable_name = name_of_struct(data1, data2, data3);
let origin = Point(0, 0, 0);
}
类单元结构体
struct unit_like_struct; // 没了,就这么简单,里边啥也没有
fn main() {
let a = unit_like_struct;
}
我也没搞懂有什么用……
等后面来修改吧。
调用
struct_name.field
结构体名称.字段 即可获取值。
如果是可变结构体的话,还可以 struct_name.field = value
赋值。
为结构体定义方法
简单来说,就是给结构体加上“内置功能”。
方法以结构体(&self)作为参数。
struct Rectangle {
width: u32,
height: u32,
}
// impl 是 implemention 实现 的简写
// impl 结构体类型名称 {}
impl Rectangle {
// 方法在 impl 中以函数的方法被定义。
// &self 是对“自己”(即被操作的结构体)的一个引用。这里一定要使用引用,因为我们不需要取得所有权,仅需要读取数据
// 这里并没有给 &self 取别名,在函数里直接使用 self 指代你的结构体即可
fn area(&self) -> u32 {
self.width * self.height
}
// 这里引入了另一个操作对象:other,类型是一个**引用**,这里除了 int, unsigned int, float, char 类型的参数都推荐使用引用
fn can_hold(&self, other: &Rectangle) -> bool {
self.width > other.width && self.height > other.height
}
}
fn main() {
let rect1 = Rectangle {
width: 30,
height: 50,
};
println!(
"The area of the rectangle is {} square pixels.",
rect1.area()
);
let rect2 = Rectangle {
width: 10,
height: 40,
};
let rect3 = Rectangle {
width: 60,
height: 45,
};
println!("Can rect1 hold rect2? {}", rect1.can_hold(&rect2));
println!("Can rect1 hold rect3? {}", rect1.can_hold(&rect3));
}
另外,把几个方法分别写进好几个 impl Rectangle {}
里也是可以的。
关联函数
所有 impl 中定义的函数都是关联函数,前面说的方法也是。
也有一些函数可以不以结构体自己的引用 &self 做参数,比如用于构造结构体的函数。
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
// 这里只有 size 一个参数,没有 self 的引用作为参数
// 区分大小写,Self 指代 Rectangle 这个数据类型,self 指代被操作的那一个结构体
// 返回 Self(Rectangle)类型
// 对于 Rust 内置的 int, unsigned int, float, char 类型可以放心的不加引用,这些类型默认会 Clone
fn square(size: u32) -> Self {
Self {
width: size,
height: size,
}
}
}
fn main() {
let square = Rectangle::quare(3);
// 调用时要写命名空间的调用符号 :: ,因为这个函数(以及上面的方法)实际上就是放在了以结构体为名的命名空间里。
// Rectangle::square() 返回了一个 Rectangle 结构体,所以 square 变量为 Rectangle 类型。
}
为枚举定义方法和关联函数的方法一样,大家可以自行尝试