橘子味的心
标题:Rust泛型

当要创建多种形式的功能时,即,函数的参数可以接受多种类型的数据。 这可以通过泛型来实现。 泛型也称为“参数多态”,其中多态是多重的,而变形是形式。

有两种方法可以提供通用代码:

  • Option<T>
  • Result<T, E>

1.Option<T>:Rust标准库提供Option,其中'T'是通用数据类型。 它提供了一种类型的泛型。

  1. enum Option<T>
  2. {
  3. Some(T),
  4. None,
  5. }
  6. Rust

在上面的例子中,enum是自定义类型,其中<T>是通用数据类型。 可以用任何数据类型替换T。下面来看看这几个示例 :

  1. let x : Option<i32> = Some(10); // 'T' is of type i32.
  2. let x : Option<bool> = Some(true); // 'T' is of type bool.
  3. let x : Option<f64> = Some(10.5); // 'T' is of type f64.
  4. let x : Option<char> = Some('b'); // 'T' is of type char.
  5. Rust

在上面的例子中,观察到'T'可以是任何类型,即i32boolf64char。 但是,如果左侧的类型与右侧的值不匹配,则会发生错误。 如下示例:

  1. let x : Option<i32> = Some(10.8);
  2. Rust

在上述情况下,左侧的类型是i32,右侧的值是f64类型。 因此,错误发生“类型不匹配”。

  1. Result <T,E>: Rust标准库提供了另一种数据类型Result <T,E>,它是两种类型的泛型,即T&E
  1. enum Result<T,E>
  2. {
  3. OK(T),
  4. Err(E),
  5. }
  6. Rust

注意:不得不使用'T''E',可以使用任何大写字母。

泛型函数

泛型可以在函数中使用,将泛型放在函数的签名中,其中指定参数的数据类型和返回值。

  • 当函数包含类型为T的单个参数时。

语法

  1. fn function_name<T>(x:T)
  2. // body of the function.
  3. Rust

上面的语法包含两部分:

  • <T> : 给定的函数是一种类型的泛型。
  • (x : T) : x 是类型 T

当函数包含多个相同类型的参数时。

  1. fn function_name<T>(x:T, y:T)
  2. // body of the function.
  3. Rust

当函数包含多个类型的参数时。

  1. fn function_name<T,U>(x:T, y:U)
  2. // Body of the function.
  3. Rust

完整代码 -

  1. fn main()
  2. {
  3. let a = vec![1,2,3,4,5];
  4. let b = vec![2.3,3.3,4.3,5.3];
  5. let result = add(&a);
  6. let result1 = add(&b);
  7. println!("The value of result is {}",result);
  8. println!("The value of result1 is {}",result1);
  9. }
  10.  
  11. fn add<T>(list:&[T])->T
  12. {
  13. let mut c =0;
  14. for &item in list.iter()
  15. {
  16. c= c+item;
  17. }
  18. }
  19. Rust

结构定义

结构也可以使用<>运算符在一个或多个字段中使用泛型类型参数。

语法:

  1. struct structure_name<T>
  2. // Body of the structure.
  3. Rust

在上面的语法中,在struct_name之后的尖括号中声明泛型类型参数,然后可以在struct定义中使用泛型类型。

下面我们来看一个简单的例子:

  1. struct Value<T>
  2. {
  3. a:T,
  4. b:T,
  5. }
  6. fn main()
  7. {
  8. let integer = Value{a:2,b:3};
  9. let float = Value{a:7.8,b:12.3};
  10. println!("integer values : {},{}",integer.a,integer.b);
  11. println!("Float values :{},{}",float.a,float.b);
  12. }
  13. Rust

执行上面示例代码,得到以下结果 -

  1. integer values : 2,3
  2. Float values : 7.8,12.3
  3. Shell

在上面的示例中,Value <T>结构在一种类型上是通用的,而ab是相同类型的。创建两个实例integerfloatInteger包含i32类型的值,float包含f64类型的值。

下面来看另一个简单的例子。

  1. struct Value<T>
  2. {
  3. a:T,
  4. b:T,
  5. }
  6. fn main()
  7. {
  8. let c = Value{a:2,b:3.6};
  9. println!("c values : {},{}",c.a,c.b);
  10. }
  11. Rust

执行上面示例代码,得到以下结果:

在上面的示例中,Value <T>在一种类型上是通用的,而ab是相同类型的。创建了一个c的实例。c包含不同类型的值,即i32f64。 因此,Rust编译器会抛出“不匹配的错误”。

枚举定义

枚举也可以使用通用数据类型。Rust标准库提供了Option <T>枚举,它包含通用数据类型。 Option <T>是一个枚举,其中T是通用数据类型。

  • Option<T>

它由两个变体组成,即Some(T)None

其中Some(T)保存类型T的值,None不包含任何值。

看看下面一段示例代码:

  1. enum Option<T>
  2. {
  3. Some(T),
  4. None,
  5. }
  6. Rust

在上面的例子中,Option是一个枚举,它在一个类型T上是通用的。 它由两个变体Some(T)None组成。

Result<T, E> :可以创建多种类型的泛型,这可以通过Result <T,E>来实现。

  1. enum Result<T,E>
  2. {
  3. OK(T),
  4. Err(E),
  5. }
  6. Rust

在上面的例子中,Result <T,E>是一个枚举,它在两种类型上是通用的,它由两个变体组成,即OK(T)Err(E)

OK(T)保持类型T的值,而Err(E)保持类型E的值。

方法定义

可以在结构和枚举上实现这些方法。下来看看一个简单的例子:

  1. struct Program<T> {
  2. a: T,
  3. b: T,
  4. }
  5. impl<T> Program<T>
  6. {
  7. fn a(&self) -> &T
  8. {
  9. &self.a
  10. }
  11. }
  12.  
  13. fn main() {
  14. let p = Program{ a: 5, b: 10 };
  15.  
  16. println!("p.a() is {}", p.a());
  17. }
  18. Rust

输出结果如下 -

  1. p.a() is 5
  2. Shell

在上面的例子中,在Program <T>上实现了a方法,该方法返回对变量a中存在的数据的引用。在impl之后声明了T,以指定在Program <T>上实现该方法。

解决歧义

Rust编译器自动推断通用参数。下面通过一个简单的场景来理解:

  1. Let mut v = Vec::new(); // creating a vector.
  2. v.push(10); // inserts integer value into the vector. Therefore, v is of i32 type.
  3. println!("{:?}", v); // prints the value of v.
  4. Rust

在上面的例子中,将整数值插入向量中。 因此,Rust编译器知道向量v的类型为i32

如果删除第二行,现在代码如下所示 -

  1. Let mut v = Vec::new(); // creating a vector.
  2. println!("{:?}", v); // prints the value of v.
  3. Rust

上面的情况将抛出“它无法推断出T的类型”的错误。

可以通过两种方式解决上述问题:

  1. 使用以下注释:
  1. let v : Vec<bool> = Vec::new();
  2. println!("{:?}",v) ;
  3. Rust
  1. 使用'turbofish':: <>运算符绑定泛型参数'T'
  1. let v = Vec :: <bool> :: new();
  2. println!("{:?}",v) ;
  3. Rust