Rust泛型
當要創建多種形式的功能時,即,函數的參數可以接受多種類型的數據。 這可以通過泛型來實現。 泛型也稱爲「參數多態」,其中多態是多重的,而變形是形式。
有兩種方法可以提供通用代碼:
-
Option<T>
-
Result<T, E>
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
類型。 因此,錯誤發生「類型不匹配」。
-
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;
}
}
結構定義
結構也可以使用<>
運算符在一個或多個字段中使用泛型類型參數。
語法:
struct structure_name<T>
// Body of the structure.
在上面的語法中,在struct_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,3
Float values : 7.8,12.3
在上面的示例中,Value <T>
結構在一種類型上是通用的,而a
和b
是相同類型的。創建兩個實例integer
和float
。 Integer
包含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);
}
執行上面示例代碼,得到以下結果:
在上面的示例中,Value <T>
在一種類型上是通用的,而a
和b
是相同類型的。創建了一個c
的實例。c
包含不同類型的值,即i32
和f64
。 因此,Rust編譯器會拋出「不匹配的錯誤」。
枚舉定義
枚舉也可以使用通用數據類型。Rust標準庫提供了Option <T>
枚舉,它包含通用數據類型。 Option <T>
是一個枚舉,其中T
是通用數據類型。
-
Option<T>
它由兩個變體組成,即Some(T)
和None
。
其中Some(T)
保存類型T
的值,None
不包含任何值。
看看下面一段示例代碼:
enum Option<T>
{
Some(T),
None,
}
在上面的例子中,Option
是一個枚舉,它在一個類型T
上是通用的。 它由兩個變體Some(T)
和None
組成。
Result<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
中存在的數據的引用。在impl
之後聲明瞭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的類型」的錯誤。
可以通過兩種方式解決上述問題:
- 使用以下注釋:
let v : Vec<bool> = Vec::new();
println!("{:?}",v) ;
- 使用
'turbofish':: <>
運算符綁定泛型參數'T'
:
let v = Vec :: <bool> :: new();
println!("{:?}",v) ;