Rust Generics
Generics is an indispensable mechanism for a programming language.
C++ uses "templates" to implement generics, while C language does not have a generic mechanism, which also makes it difficult for C language to build projects with complex types.
The generic mechanism is a mechanism for programming languages to express type abstraction, generally used for classes with determined functionality but undetermined data types, such as linked lists, maps, etc.
### Defining Generics in Functions
This is a method for selection sorting of integer numbers:
## Example
fn max(array:&)->i32{
let mut max_index=0;
let mut i=1;
while iarray{
max_index=i;
}
i+=1;
}
array
}
fn main(){
let a=[2,4,6,3,1];
println!("max={}",max(&a));
}
Output:
max = 6
This is a simple maximum value program, which can be used to process i32 numeric type data, but cannot be used for f64 type data. By using generics, we can make this function usable for various types. However, not all data types can be compared in size, so the following code is not for running, but to describe the syntax format of function generics:
## Example
fn max(array:&)->T{
let mut max_index=0;
let mut i=1;
while iarray{
max_index=i;
}
i+=1;
}
array
}
### Generics in Structs and Enums
The Option and Result enums we learned before are generics.
Both structs and enums in Rust can implement generic mechanisms.
structPoint{x:T,y:T }
This is a point coordinate struct, where T represents the numeric type describing the point coordinates. We can use it like this:
letp1=Point{x:1,y:2};letp2=Point{x:1.0,y:2.0};
The type is not declared when using it; the automatic type mechanism is used here, but type mismatch is not allowed as follows:
letp=Point{x:1,y:2.0};
When x is bound to 1, T is already set to i32, so f64 type is not allowed to appear again. If we want x and y to use different data types, we can use two generic identifiers:
structPoint{x:T1,y:T2 }
The method of representing generics in enums such as Option and Result:
enum Option { Some(T), None,}enum Result { Ok(T), Err(E),}
Both structs and enums can define methods, so methods should also implement generic mechanisms, otherwise generic classes cannot be effectively operated by methods.
## Example
struct Point{
x: T,
y: T,
}
impl Point{
fn x(&self)->&T {
&self.x
}
}
fn main(){
let p = Point { x:1, y:2};
println!("p.x = {}", p.x());
}
Output:
p.x = 1
Note that there must be after the impl keyword, because the T following it uses it as a reference. But we can also add methods for one of the generics:
impl Point { fn x(&self) -> f64 { self.x }}
The generics of the impl block itself do not hinder its internal methods from having generic capabilities:
impl Point { fn mixup(self, other: Point) -> Point { Point { x: self.x, y: other.y, } }}
The method mixup fuses the x of a Point with the y of a Point into a new point of type Point
YouTip