Rust泛型图解和用法

本文概述

  • 通用功能
  • 句法
  • 结构定义
  • 枚举定义
  • 方法定义
  • 解决歧义
当我们要创建多种形式的函数时, 即函数的参数可以接受多种类型的数据。这可以通过泛型来实现。泛型也称为” 参数多态性” , 其中poly是多个, 而morph是形式。
提供通用代码有两种方法:
  • 选项< T>
  • 结果< T, E>
Rust泛型图解和用法

文章图片
1. Option < T> :Rust标准库提供Option, 其中” T” 是通用数据类型。它提供一种以上的泛型。
enum Option< T> {Some(T), None, }

在上述情况下, enum是自定义类型, 其中< T> 是通用数据类型。我们可以将” T” 替换为任何数据类型。让我们来看一下:
let x : Option< i32> = Some(10); // 'T' is of type i32.let x : Option< bool> = Some(true); // 'T' is of type bool.let x : Option< f64> = Some(10.5); // 'T' is of type f64.let x : Option< char> = Some('b'); // 'T' is of type char.

在上述情况下, 我们观察到” T” 可以是任何类型, 即i32, bool, f64或char。但是, 如果左侧的类型和右侧的值不匹配, 则会发生错误。让我们来看一下:
let x : Option< i32> = Some(10.8);

在上述情况下, 左侧的类型为i32, 右侧的值为f64类型。因此, 错误发生” 类型不匹配” 。
2. Result < T, E> :Rust标准库提供了另一个数据类型Result < T, E> , 它对两种类型(即T&E)具有通用性:
enum Result< T, E> {OK(T), Err(E), }

注意:并非必须使用’ T’ 和’ E’ 作为约定。我们可以使用任何大写字母。 通用功能 泛型可以在函数中使用, 我们将泛型放在函数的签名中, 在函数的签名中指定了参数的数据类型和返回值。
  • 当函数包含类型为’ T’ 的单个参数时。
句法
fn function_name< T> (x:T) {// body of the function.}

上面的语法分为两部分:
  • < T> :给定的函数是一种类型的泛型。
  • (x:T):x为T类型。
当函数包含相同类型的多个参数时。
fn function_name< T> (x:T, y:T) {// body of the function.}

当函数包含多种类型的参数时。
fn function_name< T, U> (x:T, y:U){// Body of the function.}

fn main(){let a = vec![1, 2, 3, 4, 5]; let b = vec![2.3, 3.3, 4.3, 5.3]; let result = add(& a); let result1 = add(& b); println!("The value of result is {}", result); println!("The value of result1 is {}", result1); }fn add< T> (list:& [T])-> T{let mut c =0; for & item in list.iter(){c= c+item; }c}

结构定义 结构还可以使用< > 运算符在一个或多个字段中使用通用类型参数。
句法:
struct structure_name< T> {// Body of the structure.}

在以上语法中, 我们在structure_name之后的尖括号内声明泛型类型参数, 然后可以在struct定义中使用泛型类型。
让我们看一个简单的例子:
struct Value< T> {a:T, b:T, }fn main(){let integer = Value{a:2, b:3}; let float = Value{a:7.8, b:12.3}; println!("integer values : {}, {}", integer.a, integer.b); println!("Float values :{}, {}", float.a, float.b); }

输出
integer values : 2, 3Float values : 7.8, 12.3

在上面的示例中, Value < T> 结构在一种类型上是通用的, 并且a和b是同一类型。我们创建两个实例integer和float。整数包含i32类型的值, 而float包含f64类型的值。
让我们看另一个简单的例子。
struct Value< T> {a:T, b:T, }fn main(){let c = Value{a:2, b:3.6}; println!("c values : {}, {}", c.a, c.b); }

输出
Rust泛型图解和用法

文章图片
在上面的示例中, Value < T> 结构在一种类型上是通用的, 并且a和b是同一类型。我们创建一个’ c’ 的实例。 ‘ c’ 包含不同类型的值, 即i32和f64。因此, Rust编译器将引发” 不匹配的错误” 。
枚举定义 枚举也可以使用通用数据类型。Rust标准库提供了Option < T> 枚举, 用于保存通用数据类型。 Option < T> 是一个枚举, 其中” T” 是通用数据类型。
  • 选项< T>
它由两个变体组成, 即Some(T)和None。
Rust泛型图解和用法

文章图片
其中Some(T)保留T类型的值, 而None不包含任何值。
我们看看吧:
enum Option< T> {Some(T), None, }

在上述情况下, Option是一个枚举, 在一个类型” T” 上是通用的。它由两个变量Some(T)和None组成。
  • 结果< T, E> :我们可以创建多种类型的泛型。这可以通过Result < T, E> 实现。
enum Result< T, E> {OK(T), Err(E), }

在上述情况下, Result < T, E> 是一个对两种类型通用的枚举, 它由两个变体(即OK(T)和Err(E))组成。
OK(T)保留类型’ T’ 的值, 而Err(E)保留类型’ E’ 的值。
方法定义 我们可以在结构体和枚举上实现这些方法。
让我们看一个简单的例子:
struct Program< T> {a: T, b: T, }impl< T> Program< T> {fn a(& self) -> & T {& self.a}}fn main() {let p = Program{ a: 5, b: 10 }; println!("p.a() is {}", p.a()); }

输出
p.a() is 5

在上面的示例中, 我们在Program < T> 上实现了名为” a” 的方法, 该方法返回对变量a中存在的数据的引用。
我们在暗示之后声明了” T” , 以表明我们正在Program < T> 上实现该方法。
解决歧义 Rust编译器会自动推断通用参数。让我们通过一个简单的场景来理解这一点:
Let mut v = Vec::new(); // creating a vector.v.push(10); // inserts integer value into the vector. Therefore, v is of i32 type.println!("{:?}", v); // prints the value of v.

在上述情况下, 我们将整数值插入向量中。因此, Rust编译器知道向量v的类型为i32。
如果我们删除第二行, 那么它看起来像;
Let mut v = Vec::new(); // creating a vector.println!("{:?}", v); // prints the value of v.

上述情况将引发一个错误, 即” 它无法推断T的类型” 。
  • 我们可以通过两种方式解决上述情况:
1.我们可以使用以下注释:
let v : Vec< bool> = Vec::new(); println!("{:?}", v) ;

【Rust泛型图解和用法】2.我们可以使用’ turbofish’ :: < > 运算符来绑定通用参数’ T’ :
let v = Vec :: < bool> :: new(); println!("{:?}", v) ;

    推荐阅读