Rust教程(9):语言篇[下] - 方法
2023-12-08 21:11:20
在昨天的《写给前端看的Rust教程(8)语言篇[中]》我们介绍了如何创建struct,rust中的struct与JavaScript中的class有相似之处,本文我们将介绍struct的方法以及Rust语言中闭包、trait、生命周期、泛型、宏、所有权、借用和unsafe的使用。
1. 方法
方法是Rust语言中定义在结构体上的函数,它可以访问结构体中的数据并对其进行操作。方法的定义方式与普通函数相似,但需要在函数名前加上struct的名字和一个点(.`)。
struct Point {
x: i32,
y: i32,
}
impl Point {
fn new(x: i32, y: i32) -> Point {
Point {
x: x,
y: y,
}
}
fn add(&self, other: &Point) -> Point {
Point {
x: self.x + other.x,
y: self.y + other.y,
}
}
}
fn main() {
let point1 = Point::new(1, 2);
let point2 = Point::new(3, 4);
let point3 = point1.add(&point2);
println!("The point3 is ({}, {})", point3.x, point3.y);
}
上述代码中,我们定义了一个Point
结构体,并在其中定义了两个方法:new()
和add()
。new()
方法用于创建新的Point
实例,add()
方法用于将两个Point
实例相加并返回一个新的Point
实例。
在main()
函数中,我们首先创建了两个Point
实例point1
和point2
,然后调用point1.add(&point2)
来将这两个实例相加并将其赋值给point3
。最后,我们使用println!()
函数将point3
的坐标打印到控制台上。
2. 闭包
闭包是Rust语言中的一种匿名函数,它可以捕获其周围环境的变量并将其作为自己的参数。闭包的定义方式与普通函数相似,但需要使用||
来替代函数名。
fn main() {
let add = |x: i32, y: i32| -> i32 {
x + y
};
let result = add(1, 2);
println!("The result is {}", result);
}
上述代码中,我们定义了一个闭包add
,它接受两个i32类型的参数并返回一个i32类型的结果。然后,我们调用闭包add
并将其结果赋值给result
。最后,我们使用println!()
函数将result
的值打印到控制台上。
3. trait
trait是Rust语言中的一种接口,它定义了一组方法和属性,这些方法和属性可以被任何实现了该trait的类型实现。trait的定义方式与普通结构体相似,但需要使用trait
。
trait Drawable {
fn draw(&self);
}
struct Circle {
radius: f32,
}
impl Drawable for Circle {
fn draw(&self) {
println!("Drawing a circle with radius {}.", self.radius);
}
}
fn main() {
let circle = Circle {
radius: 1.0,
};
circle.draw();
}
上述代码中,我们定义了一个名为Drawable
的trait,它定义了一个draw()
方法。然后,我们定义了一个名为Circle
的结构体,它实现了Drawable
trait。最后,我们在main()
函数中创建了一个Circle
实例并调用它的draw()
方法。
4. 生命周期
生命周期是Rust语言中的一种类型系统,它用于跟踪变量和引用在内存中的生存时间。生命周期的定义方式与普通类型相似,但需要使用'static
关键字。
fn main() {
let x: &'static str = "hello";
println!("The value of x is {}", x);
}
上述代码中,我们定义了一个名为x
的变量,它的类型是&'static str
,这表示x
是一个引用,它指向一个生存期为'static
的字符串。'static
生命周期表示该字符串在程序的整个生命周期内都存在。
5. 泛型
泛型是Rust语言中的一种类型系统,它允许我们定义可以处理不同类型数据的函数和结构体。泛型的定义方式与普通类型相似,但需要使用尖括号<>
来指定泛型参数。
fn max<T: Ord>(a: T, b: T) -> T {
if a > b {
a
} else {
b
}
}
fn main() {
let x = max(1, 2);
let y = max("hello", "world");
println!("The maximum of 1 and 2 is {}", x);
println!("The maximum of \"hello\" and \"world\" is {}", y);
}
上述代码中,我们定义了一个名为max()
的泛型函数,它接受两个相同类型的参数并返回一个相同类型的结果。泛型参数T
必须实现Ord
trait,这表示它可以被比较。然后,我们在main()
函数中调用max()
函数并将其结果赋值给x
和y
。最后,我们使用println!()
函数将x
和y
的值打印到控制台上。
6. 宏
宏是Rust语言中的一种元编程工具,它允许我们定义自己的语法和函数。宏的定义方式与普通函数相似,但需要使用macro_rules!
关键字。
macro_rules! my_macro {
($($x:expr),*) => {
println!("The values are: {}", $($x),*);
};
}
fn main() {
my_macro!(1, 2, 3, 4, 5);
}
上述代码中,我们定义了一个名为my_macro!
的宏,它接受一组逗号分隔的表达式并将其打印到控制台上。然后,我们在main()
函数中调用my_macro!
宏并将其结果打印到控制台上。
7. 所有权
所有权是Rust语言中的一种内存管理机制,它规定了每个变量只能有一个所有者。当一个变量的所有权被转移给另一个变量时,原变量的所有权就会被释放。所有权的转移可以通过赋值操作或函数调用来实现。
fn main() {
let x = 1;
let y = x;
println!("The value of x is {}", x);
println!("The value of y is {}", y);
}
上述代码中,我们定义了一个名为x
的变量,它的类型是i32,并将其值设置为1。然后,我们定义了一个名为y
的变量,它的类型是i32,并将x
的所有权转移给y
。此时,x
的所有权已被释放,因此我们无法再访问它。
8. 借用
借用是Rust语言中的一种内存管理机制,它允许我们临时访问另一个变量的数据。借用的定义方式与普通变量相似,但需要使用&
符号。
fn main() {
let x = 1;
let y = &x;
println!("The value of x is {}", x);
println!("The value of y is {}", y);
}
上述代码中,我们定义了一个名为x
的变量,它的类型是i32,并将其值设置为1。然后,我们定义了一个名为y
的变量,它的类型是&i32
,并将x
的借用赋给y
。此时,y
可以访问x
的数据,但x
的所有权仍然属于x
。
9. unsafe
unsafe
关键字是Rust语言中的一种特殊关键字,它允许我们访问未经安全检查的代码。unsafe
关键字只能用于实现unsafe trait或unsafe函数。
unsafe fn main() {
let x = 1;
let y = &mut x;
*y = 2;
println!("The value of x is {}", x);
}
上述代码中,我们定义了一个名为x
的变量,它的类型是