📜  Rust泛型

📅  最后修改于: 2021-01-08 13:53:21             🧑  作者: Mango

锈泛型

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

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

  • 选项
  • 结果

1. Option :Rust标准库提供Option其中“ T”是通用数据类型。它提供一种以上的泛型。

 enum Option
{
    Some(T),
    None,
}

在上述情况下, enum是自定义类型,其中是通用数据类型。我们可以将“ T”替换为任何数据类型。让我们来看一下:

let x : Option = Some(10);  // 'T' is of type i32.
let x : Option = Some(true);  // 'T' is of type bool.
let x : Option = Some(10.5); // 'T' is of type f64.
let x : Option = Some('b'); // 'T' is of type char. 

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

 let x : Option = Some(10.8); 

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

2. Result :Rust标准库提供了另一个数据类型Result ,它对两种类型通用,即T&E:

   enum Result
    {
       OK(T),
         Err(E),
 } 

注意:并非必须使用'T'和'E'作为约定。我们可以使用任何大写字母。

通用功能

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

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

句法:

 fn function_name(x:T) 
{
   // body of the function.
}

上面的语法分为两部分

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

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

 fn function_name(x:T, y:T) 
{
   // body of the function.
}

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

 fn function_name(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(list:&[T])->T
{
  let mut c =0;
  for &item in list.iter()
  {
    c= c+item;
  }
  c}

结构定义

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

句法:

 struct structure_name 
{
   // Body of the structure.
}

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

让我们看一个简单的例子

 struct Value
{
  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,3
Float values : 7.8,12.3

在上面的示例中,Value 结构在一种类型上是通用的,并且a和b是同一类型。我们创建两个实例integer和float。整数包含i32类型的值,而float包含f64类型的值。

让我们看另一个简单的例子。

 struct Value
{
  a:T,
  b:T,
}
fn main()
{
  let c = Value{a:2,b:3.6};
  println!("c values : {},{}",c.a,c.b);
 }

输出:

在上面的示例中,Value 结构在一种类型上是通用的,并且a和b是同一类型。我们创建“ c”的实例。 “ c”包含不同类型的值,即i32和f64。因此,Rust编译器将引发“不匹配的错误”。

枚举定义

枚举也可以使用通用数据类型。Rust标准库提供了Option 枚举,用于保存通用数据类型。 Option 是一个枚举,其中“ T”是通用数据类型。

  • 选项

它包含两个变体,即Some(T)和None。

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

我们看看吧:

 enum Option
{
    Some(T),
    None,
}

在上述情况下,选项是对一种类型“ T”通用的枚举。它由两个变量Some(T)和None组成。

  • Result :我们可以创建多种类型的泛型。这可以通过Result 实现。
 enum Result
{
    OK(T),
    Err(E),
} 

在上述情况下,Result 是一个对两种类型通用的枚举,它由两个变体(即OK(T)和Err(E))组成。

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

方法定义

我们可以在结构体和枚举上实现这些方法。

让我们看一个简单的例子:

 struct Program {
    a: T,
    b: T,
}
impl Program 
{
    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 上实现了名为“ a”的方法,该方法返回对变量a中存在的数据的引用。

我们在暗示之后声明了“ T”,以表明我们正在Program 上实现该方法。

解决歧义

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 = Vec::new();
println!("{:?}",v) ;

2.我们可以通过使用'turbofish':: <>运算符来绑定通用参数'T':

let v = Vec ::  :: new();
println!("{:?}",v) ;