【百例RUST - 013】泛型
第一章 基础概述
第01节 如果不用泛型
实际案例:
如果我们没有泛型,当为不同的类型定义逻辑相同的函数的时候,可能出现下面的情况
rust
fn main(){
let _a: i8 = return_i8(2i8);
let _b: i16 = return_i16(2i16);
let _c: i32 = return_i32(2i32);
let _d: i64 = return_i64(2i64);
let _e: u8 = return_u8(2u8);
let _f: u16 = return_u16(2u16);
let _g: u32 = return_u32(2u32);
let _h: u64 = return_u64(2u64);
}
// 如果没有泛型的情况下, 当不同的类型定义逻辑相同的函数的情况下, 可能会出现下面的情况:
fn return_i8(v: i8) -> i8{ v }
fn return_i16(v: i16) -> i16{ v }
fn return_i32(v: i32) -> i32{ v }
fn return_i64(v: i64) -> i64{ v }
fn return_u8(v: u8) -> u8{ v }
fn return_u16(v: u16) -> u16{ v }
fn return_u32(v: u32) -> u32{ v }
fn return_u64(v: u64) -> u64{ v }
这样的操作,会显得代码写出来很繁琐,因为他们逻辑完全相同。
第02节 如果使用泛型
那么我们可以使用泛型完成上述的功能实现。
案例代码
rust
fn main(){
let _a: i8 = return_value(2i8);
let _b: i16 = return_value(2i16);
let _c: i32 = return_value(2i32);
let _d: i64 = return_value(2i64);
let _e: u8 = return_value(2u8);
let _f: u16 = return_value(2u16);
let _g: u32 = return_value(2u32);
let _h: u64 = return_value(2u64);
}
// 使用泛型的写法
fn return_value<T> (v : T) -> T { v }
第03节 结论
通过上述的案例,我们可以得到下面的几点结论
1、泛型是具体类型或者其它属性的抽象代替,用于减少代码的重复。
2、在编写Rust代码时,可以用泛型来表示各种各样的数据类型,等到编译阶段,泛型则被替换成它所代表的的具体的数据类型。
注意事项
在 Rust 当中, 使用泛型不会造成持续上的性能损失。
1、因为 Rust 通过在编译时进行泛型代码的单态化来保存效率。(就是在编译时, 把泛型换成了具体的类型)
2、单态化是通过填充编译时使用的具体类型, 将通过代码转换为特定代码的过程
第二章 常用场景
第01节 在结构体中定义泛型
在结构体当中,定义泛型
基础案例代码
rust
#[derive(Debug)]
struct Point<T> {
x : T,
y : T,
}
fn main(){
// 当 point的两个字段都是整型
let integer: Point<i32> = Point{ x: 1, y:2};
println!("{:?}", integer);
// 当 point的两个字段都是浮点型
let float : Point<f32> = Point { x: 0.99, y: 1.99 };
println!("{:?}", float);
}
// Point { x: 1, y: 2 }
// Point { x: 0.99, y: 1.99 }
在结构体当中,定义不同的类型
rust
#[derive(Debug)]
struct Point<M, N> {
x : M,
y : N,
}
fn main(){
let a: Point<i32, f64> = Point{x : 1, y: 2.0};
println!("{:?}", a);
let b: Point<f64, i32> = Point{x: 1.99, y:3};
println!("{:?}", b);
}
// Point { x: 1, y: 2.0 }
// Point { x: 1.99, y: 3 }
第02节 在枚举当中定义泛型
系统标准库的案例
在系统库 Option 当中的代码如下:
rust
enum Option<T> {
Some(T),
None,
}
同样的案例,还有 Result 的类型,其定义如下:
rust
enum Result<T, E>{
Ok(T),
Err(E),
}
下面我们列举,自定义的枚举中,编写的泛型案例
rust
#[derive(Debug)]
enum Message<T,U>{
Msg1(u32),
Msg2(T),
Msg3(U),
}
fn main(){
let _msg1: Message<u32, String> = Message::Msg1(1u32);
let _msg2: Message<u8, String> = Message::Msg2(2u8);
let _msg3: Message<u8, String> = Message::Msg3("hello".to_string());
println!("{:?}", _msg1);
println!("{:?}", _msg2);
println!("{:?}", _msg3);
}
// Msg1(1)
// Msg2(2)
// Msg3("hello")
第03节 在方法当中定义泛型
案例1
rust
#[derive(Debug)]
struct Point<T>{
x : T,
y : T,
}
impl <T> Point<T>{
fn get_x(&self) -> &T{
&self.x
}
fn get_y(&self) -> &T{
&self.y
}
}
fn main(){
let p: Point<i32> = Point{ x:1, y:2};
println!("{:?}", p);
println!("x = {}", p.get_x());
println!("y = {}", p.get_y());
}
// Point { x: 1, y: 2 }
// x = 1
// y = 2
案例2
rust
#[derive(Debug)]
struct Point<T, U>{
x : T,
y : U,
}
impl <T, U> Point<T, U>{
fn minxup<V, W> (self, other:Point<V,W>) -> Point<T,W>{
Point { x: self.x, y: other.y }
}
}
fn main(){
let p1: Point<i32, f64> = Point {x:5, y:10.04};
let p2:Point<&str, char>= Point {x:"hello", y:'c'};
let p3: Point<i32, char> = p1.minxup(p2);
// 在这里 p1.minxup(p2) ---> 传入到上面的函数中 self=p1 other=p2
// 因为 self=p1 那么 x 的取值应该是 p1 的取值, 也就是 p3.x = p1.x ---> p3.x = 5
// 因为 other=p2 那么 y 的取值应该是 p2 的取值, 也就是 p3.y = p2.y ---> p3.y = 'c'
println!("p3.x = {}, p3.y = {}", p3.x, p3.y);
}
// p3.x = 5, p3.y = c