Generics
-
Generics are a way to define functions, structs, enums, and methods that work with any type
-
Generics allows us to reduce code duplication
-
Does not affect performance because Rust uses monomorphization to create specific implementations of generic code at compile time
-
Tis a generic type parameter
fn main() {
let number_list = vec![34, 50, 25, 100, 65];
let largest = get_largest(number_list);
println!("The largest number is {}", largest);
}
fn get_largest<T>(number_list: Vec<T>) -> T {
let mut largest = number_list[0];
for &number in number_list.iter() {
if number > largest {
largest = number;
}
}
largest
}⛔
Error:
binary operation > cannot be applied to type T
fn main() {
let number_list = vec![34, 50, 25, 100, 65];
let largest = get_largest(number_list);
println!("The largest number is {}", largest);
}
fn get_largest<T>(number_list: Vec<T>) -> T {
let mut largest = number_list[0];
for &number in number_list.iter() {
if number > largest {
largest = number;
}
}
largest
}fn main() {
let number_list = vec![34, 50, 25, 100, 65];
let largest = get_largest(number_list);
println!("The largest number is {}", largest);
}
fn get_largest<T: PartialOrd + Copy>(number_list: Vec<T>) -> T {
let mut largest = number_list[0];
for &number in number_list.iter() {
if number > largest {
largest = number;
}
}
largest
}PartialOrdtrait is used to compare valuesCopytrait is used to copy values
struct Point<T> {
x: T,
y: T,
}
fn main() {
let integer = Point { x: 5, y: 10 };
let float = Point { x: 1.0, y: 4.0 };
println!("integer.x = {}", integer.x);
println!("float.x = {}", float.x);
}-
Pointstruct with generic typeT -
Problem: both
xandymust have the same type
struct Point<T, U> {
x: T,
y: U,
}
fn main() {
let integer = Point { x: 5, y: 1.0 };
let float = Point { x: 1.0, y: 4.0 };
println!("integer.x = {}", integer.x);
println!("float.x = {}", float.x);
}Option&Resultenums are generics too
struct Point<T> {
x: T,
y: T,
}
impl<T> Point<T> {
fn x(&self) -> &T {
&self.x
}
}
impl Point<f64> {
fn y(&self) -> &f64 {
&self.y
}
}
fn main() {
let p = Point { x: 5, y: 10 };
p.x();
let p = Point { x: 5.0, y: 10.0 };
p.y();
println!("p.x = {}", p.x());
}y()method is only available forPoint<f64>
struct Point<T, U> {
x: T,
y: U,
}
impl<T, U> Point<T, U> {
fn mixup<V, W>(self, other: Point<V, W>) -> Point<T, W> {
Point {
x: self.x,
y: other.y,
}
}
}
fn main() {
let p1 = Point { x: 5, y: 10.4 };
let p2 = Point { x: "Hello", y: 'c' };
let p3 = p1.mixup(p2);
println!("p3.x = {}, p3.y = {}", p3.x, p3.y);
}mixupmethod is used to mix twoPointinstancesimpl<T, U> Point<T, U>is used to define methods forPointstructfn mixup<V, W>(self, other: Point<V, W>) -> Point<T, W>is a method that takes anotherPointinstance and returns a newPointinstance