RUST 每日一省:泛型

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

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

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

泛型容器

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

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

泛型枚举

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

enum Option<T> {
 Some(T),
 None,
}

fn output(age:i32) -> Option<i32>{
    if age > 18{
        return Some(age)
    }else{
        return None
    }
}

fn main() {
 let ret1 = output(19);
 println!("{:?}",ret1);
 let ret2 = output(13);
 println!("{:?}",ret2);

}

泛型结构体

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

#[derive(Debug)]
struct Num<T,U> {
    data: Option<T>,
    num: U
}
#[derive(Debug)]
struct Nu<T> {
    data: Option<T>,
    num: T
}
fn main() {
 let ret = Num{data:Some(1), num:"hello"};
 println!("{:?}",ret);
 //let ret = Nu{data:Some(1), num:"hello"};
 //println!("{:?}",ret);
}

泛型函数

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

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

fn foo<T>(x: T) -> T {
 return x;
}


fn main() {
 println!("{}", foo(5));
 println!("{}", foo("hello".to_string()));
}

//fn foo(x: i32) -> i32 {
// return x;
//}

//fn foo<T>(x: String) -> String {
// return x;
//}

泛型impl

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

#[derive(Debug)]
struct Container<T> {
    item: T
}

impl<T> Container<T> {
   fn new(item: T) -> Self {
        Container { item }
   }
}
fn main() {
    let c = Container::new(9);
    println!("{:?}",c);
}

猜你喜欢

转载自blog.csdn.net/xq723310/article/details/130439182
今日推荐