Rust 基础(06) 泛型
泛型
什么是泛型,泛型的作用,泛型的优势等本文不做介绍,本文只将泛型在 Rust 当中的使用方法.
泛型方法
一个比较两个数大小的并返回其中较大的一个数:
fn larget<T: std::cmp::PartialOrd>(a: T, b: T) -> T {
if a >= b {
a
} else {
b
}
}
泛型方法是在函数定义时在函数名后添加一对尖括号(< >
),并在里面填入泛型T
,然后通过冒号为泛型绑定属性.如 std::cmp::PartialOrd
就表示这个泛型具备可比较性,即能运算大小.而在后面就可以把T
当作一种数据类型为所参数指定,包括返回值数据类型.如果需要绑定多个属性则可以通过 +
连接属性,如下面这样.
fn larget<T: std::cmp::PartialOrd+std::cmp::PartialEq>(a: T, b: T) -> T {
if a >= b {
a
} else {
b
}
}
泛型结构体
struct Point<T> {
x: T,
y: T,
}
虽然泛型可以在一个结构体中使用多个泛型(函数同样),但是并不建议在同一个结构体中出现多个泛型,即并不推荐如下写法:
struct Point<T,U> {
x: T,
y: T,
z: U,
}
泛型结构体也支持嵌套:
struct Line<T> {
x: Point<T>,
y: Point<T>,
}
泛型结构体方法实现
为泛型结构体定义方法主要分为两种,一种是像下面这样为泛型类型定义方法,只要是具备某个 Traits 的类型的结构体都能调用这个方法.
impl<T: Clone + std::cmp::PartialOrd> Point<T> {
fn max(&self)->T {
if self.x >= self.y && self.x >= self.z {
self.x.clone()
} else if self.y >= self.z {
self.y.clone()
} else {
self.z.clone()
}
}
}
另外一种是只为某种指定的数据类型定义方法,即只有这个数据类型的结构体才能够调用该方法.
impl Point<f32> {
fn distance_to_origin(&self) -> f32 {
(self.x.powi(2) + self.y.powi(2) + self.z.powi(2)).sqrt()
}
}
为结构体实现某个 Traits
为结构体实现某些 Traits 则可以定义结构体的一些公共行为,如实现 std::fmt::Display
之后就可以通过 println!
来按照指定格式打印自己的结构体.
impl<T: std::fmt::Display> std::fmt::Display for Point<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "({}, {}, {})", self.x, self.y, self.z)
}
}
也可以为一些 Traits 定义公共行为:
fn show1<T: std::fmt::Display>(a:T) {
println!("show1: {}", a);
}
fn show2(a: impl std::fmt::Display) {
println!("show2: {}", a);
}
PS: 这两个函数是等价的 show2 的写法是 show1 的一种语法糖,而对于 show2 这种写法就十分与 Golang 的把 interface 作为参数类型写在函数定义当中相似.
自动派生
#[derive(PartialEq, Default)]
struct Point<T> {
x: T,
y: T,
z: T,
}