定义
定义结构体相当于创建了自定义类型。
结构体用来把一些相关的属性封装(encapsulate )进一个类型中
结构体遵循PascalCase
写法,即首字母大写
可变性定义在整体上而不是单个属性上,Rust
不允许只将某个字段标识为可变
有三种结构体:
- 类C的结构体(C-like structs)
- 属性间逗号分隔(comma-separated)
- 花括号包围(Brace-enclosed list)
- 与
OOP
语言中的类(除方法外)定义相似 - 通过点运算符(dot notation)访问成员
- 定义中是
name:type
- 实例中是
name:value
- 元组结构体(Tuple structs)
- 只定义了类型,类型间逗号分隔
- 括号包围(parenthesized)
- 可以看作命名的元组
- 通过点运算符(dot notation)加
index
访问成员
- 单元结构体(Unit structs)
- 没有成员
- 代表一个新的类型
- 在泛型(generics)中使用
When regarding OOP in Rust, attributes and methods are placed separately on structs and traits. Structs contain only attributes, traits contain only methods. They are getting connected via impls.
Rust
的OOP
里,属性和方法分别放到**structs**
和**traits**
中,Structs
只包含属性,traits
中只包含方法,他们通过impl
关键字联系起来
实例:
struct Color {
red: u8,
green: u8,
blue: u8,
}
fn main() {
// 结构体默认不可变
// 只能给struct整体,不能单独给属性指定mut
let mut link_color = Color {
red: 0,
green: 0,
blue: 255,
};
link_color.blue = 238; // Link Color = rgb(0, 0, 238)
// 使用 .. 从其他结构体取值
let blue = Color {
blue: 255,
..link_color
}; // Blue = rgb(0, 0, 255)
// 使用let绑定解构blue
let Color {
red: r,
green: g,
blue: b,
} = blue;
r, g, b三个变量从blue中获取了值
}
结构体更新语法
使用 ..
语法指定剩余未显式设置值的字段应有与给定实例对应字段相同的值。
let mut user1 = User {
email: String::from("someone@example.com"),
username: String::from("someusername123"),
active: true,
sign_in_count: 1,
};
let user2 = User {
email: String::from("another@example.com"),
username: String::from("anotherusername567"),
..user1
};
解构赋值
从结构体实例中解构值到对应的变量中
let mut user1 = User {
email: String::from("someone@example.com"),
username: String::from("someusername123"),
active: true,
sign_in_count: 1,
};
let User { email,username,active,sign_in_count }= user;
println!("{}",email);
方法定义
方法在结构体的上下文中被定义,结构体的每个实例都拥有这些方法
方法的第一个参数总是 self
,它指向调用该方法的结构体实例。
通常使用&self
或者&mut self
。
使用self
会获取实例的所有权,这种技术通常用在当方法将self
转换成别的实例的时候,这时我们想要防止调用者在转换之后使用原始的实例。
定义impl
块来为struct
定义方法:
#[derive(Debug)]
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
}
fn main() {
let rect1 = Rectangle { width: 30, height: 50 };
println!(
"The area of the rectangle is {} square pixels.",
rect1.area()
);
}
自动引用/解引用
Rust
有一个叫自动引用和解引用(automatic referencing and dereferencing)的功能。
方法调用是Rust
中少数几个拥有这种行为的地方。 、
他是这样工作的:当使用object.something()
调用方法时,Rust
会自动为 object
添加 &、&mut 或 *
以便使 object
与方法签名匹配。也就是说,这些代码是等价的: p1.distance(&p2);
(&p1).distance(&p2);
因为方法有一个明确的接收者——self
的类型。在给出接收者和方法名的前提下,Rust
可以明确地计算出方法是仅仅读取(&self
),做出修改(&mut self
)或者是获取所有权(self
)。事实上,Rust
对方法接收者的隐式借用让所有权在实践中更友好。
示例:
// 引入 Debug trait
#[derive(Debug)]
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
}
fn main() {
let rect = Rectangle {
width: 50,
height: 30,
};
// Rust 会自动加引用,实际调用代码为:(&rect).area()
println!("the are is:{}", rect.area());
// Rust 会自动解引用,实际调用代码为:(*rect1).area()
let rect1 = ▭
println!("the are is:{}", rect1.area());
// :? 告诉 println! 使用叫做 Debug 的输出格式。
// Debug 是一个 trait,以一种对开发者有帮助的方式打印结构体,
println!("rect is:{:#?}",rect1);
}
关联函数
关联函数 不以self
作为参数
它属于结构体所有而不是实例,位于结构体的命名空间中,类似于其他语言类定义中的静态方法
通过双冒号访问 **::**
,例如String::from()
通常用来做构造函数
示例:
impl Rectangle {
fn square(size: u32) -> Rectangle {
Rectangle { width: size, height: size }
}
}