【百例RUST - 013】泛型
【百例RUST - 013】泛型
第一章 基础概述
第01节 如果不用泛型
实际案例:
如果我们没有泛型,当为不同的类型定义逻辑相同的函数的时候,可能出现下面的情况
fnmain(){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);}// 如果没有泛型的情况下, 当不同的类型定义逻辑相同的函数的情况下, 可能会出现下面的情况:fnreturn_i8(v:i8)->i8{v}fnreturn_i16(v:i16)->i16{v}fnreturn_i32(v:i32)->i32{v}fnreturn_i64(v:i64)->i64{v}fnreturn_u8(v:u8)->u8{v}fnreturn_u16(v:u16)->u16{v}fnreturn_u32(v:u32)->u32{v}fnreturn_u64(v:u64)->u64{v}这样的操作,会显得代码写出来很繁琐,因为他们逻辑完全相同。
第02节 如果使用泛型
那么我们可以使用泛型完成上述的功能实现。
案例代码
fnmain(){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);}// 使用泛型的写法fnreturn_value<T>(v:T)->T{v}第03节 结论
通过上述的案例,我们可以得到下面的几点结论
1、泛型是具体类型或者其它属性的抽象代替,用于减少代码的重复。 2、在编写Rust代码时,可以用泛型来表示各种各样的数据类型,等到编译阶段,泛型则被替换成它所代表的的具体的数据类型。注意事项
在 Rust 当中, 使用泛型不会造成持续上的性能损失。 1、因为 Rust 通过在编译时进行泛型代码的单态化来保存效率。(就是在编译时, 把泛型换成了具体的类型) 2、单态化是通过填充编译时使用的具体类型, 将通过代码转换为特定代码的过程第二章 常用场景
第01节 在结构体中定义泛型
在结构体当中,定义泛型
基础案例代码
#[derive(Debug)]structPoint<T>{x:T,y:T,}fnmain(){// 当 point的两个字段都是整型letinteger:Point<i32>=Point{x:1,y:2};println!("{:?}",integer);// 当 point的两个字段都是浮点型letfloat:Point<f32>=Point{x:0.99,y:1.99};println!("{:?}",float);}// Point { x: 1, y: 2 }// Point { x: 0.99, y: 1.99 }在结构体当中,定义不同的类型
#[derive(Debug)]structPoint<M,N>{x:M,y:N,}fnmain(){leta:Point<i32,f64>=Point{x:1,y:2.0};println!("{:?}",a);letb: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当中的代码如下:
enumOption<T>{Some(T),None,}同样的案例,还有Result的类型,其定义如下:
enumResult<T,E>{Ok(T),Err(E),}下面我们列举,自定义的枚举中,编写的泛型案例
#[derive(Debug)]enumMessage<T,U>{Msg1(u32),Msg2(T),Msg3(U),}fnmain(){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
#[derive(Debug)]structPoint<T>{x:T,y:T,}impl<T>Point<T>{fnget_x(&self)->&T{&self.x}fnget_y(&self)->&T{&self.y}}fnmain(){letp: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
#[derive(Debug)]structPoint<T,U>{x:T,y:U,}impl<T,U>Point<T,U>{fnminxup<V,W>(self,other:Point<V,W>)->Point<T,W>{Point{x:self.x,y:other.y}}}fnmain(){letp1:Point<i32,f64>=Point{x:5,y:10.04};letp2:Point<&str,char>=Point{x:"hello",y:'c'};letp3: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