当前位置:   article > 正文

RUST 每日一省:泛型_rust 泛型

rust 泛型

        泛型是指把类型抽象成一种“参数”, 数据和算法都针对这种抽象的类型参数来实现, 而不针对具体类型。 当我们需要真正使用的时候, 再具体化、 实例化类型参数。 使用泛型可以编写更为抽象的代码, 减少工作量。

        Rust中的泛型属于静多态, 它是一种编译期多态。 在编译期,不管是泛型枚举,还是泛型函数和泛型结构体, 都会被单态化。单态化是编译器进行静态分发的一种策略。 

        使用不同类型参数将泛型类型单体化后, 获得的是完全不同的具体类型。 如Option<i32>和Option<i64>是完全不同的类型, 不可通用, 也不可相互转换。 当编译器生成代码的时候, 它会为每一个不同的泛型参数生成不同的代码。

泛型容器

        最常见的泛型应用莫过于容器,Vec<T>、HashMap<K, V>都是泛型类型的应用。比如,Vec<T>在使用中可以指定T的类型为i32或String等——Vec<i32>或者Vec<String>。

  1. fn main() {
  2. let mut vec_int: Vec<i32> = vec![10, 20];
  3. vec_int.push(30);
  4. }

泛型枚举

        泛型枚举是指枚举值类型是泛型类型。标准库提供的Option<T>就是一个应用广泛的泛型枚举。Option<T>表示可能有值,也可能无值这一抽象概念,Some(T)表示可能的值可以是任意类型T,None表示不存在。

  1. enum Option<T> {
  2. Some(T),
  3. None,
  4. }
  5. fn output(age:i32) -> Option<i32>{
  6. if age > 18{
  7. return Some(age)
  8. }else{
  9. return None
  10. }
  11. }
  12. fn main() {
  13. let ret1 = output(19);
  14. println!("{:?}",ret1);
  15. let ret2 = output(13);
  16. println!("{:?}",ret2);
  17. }

泛型结构体

        泛型类型的结构体是指结构体的字段类型是泛型类型,它可以拥有一个或多个泛型类型。定义泛型结构体时,可以在结构体名称后面带上<T>或<T, U>等,在定义字段的类型时使用T或U。我们在定义Num<T, U>时仅使用了两个个泛型,T和U可以相同也可以不同。如果是Nu<T>这个定义表明Nu<T>结构体对某个类型T是通用的。字段data与num都同时属于这个类型。假如我们像下边注释掉的代码一样使用不同的值类型来创建Nu<T>实例,那么代码是无法通过编译的。

  1. #[derive(Debug)]
  2. struct Num<T,U> {
  3. data: Option<T>,
  4. num: U
  5. }
  6. #[derive(Debug)]
  7. struct Nu<T> {
  8. data: Option<T>,
  9. num: T
  10. }
  11. fn main() {
  12. let ret = Num{data:Some(1), num:"hello"};
  13. println!("{:?}",ret);
  14. //let ret = Nu{data:Some(1), num:"hello"};
  15. //println!("{:?}",ret);
  16. }

泛型函数

        函数的参数和返回值都可以是泛型类型,带有泛型类型的参数或返回值的函数叫作泛型函数。泛型函数不要求所有参数都是泛型,可以只是某个参数是泛型。在定义泛型函数时可以在函数名称后面带上<T>,在定义参数或返回值的类型时使用T。

        编译之后的foo(5)和foo("hello".to_string()),分别生成对应的foo函数,fn foo(x:i32)->i32和fn foo(x: String)->String。

  1. fn foo<T>(x: T) -> T {
  2. return x;
  3. }
  4. fn main() {
  5. println!("{}", foo(5));
  6. println!("{}", foo("hello".to_string()));
  7. }
  8. //fn foo(x: i32) -> i32 {
  9. // return x;
  10. //}
  11. //fn foo<T>(x: String) -> String {
  12. // return x;
  13. //}

泛型impl

        impl的时候也可以使用泛型。 在impl<Trait>for<Type>{}这个语法结构中, 泛型类型既可以出现在<Trait>位置, 也可以出现在<Type>位置。与其他地方的泛型一样, impl块中的泛型也是先声明再使用。 在impl块中出现的泛型参数, 需要在impl关键字后面用尖括号声明。

  1. #[derive(Debug)]
  2. struct Container<T> {
  3. item: T
  4. }
  5. impl<T> Container<T> {
  6. fn new(item: T) -> Self {
  7. Container { item }
  8. }
  9. }
  10. fn main() {
  11. let c = Container::new(9);
  12. println!("{:?}",c);
  13. }

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/运维做开发/article/detail/951259
推荐阅读
相关标签
  

闽ICP备14008679号