Generics
Uma função genérica trabalha com um tipo que é decidido no local da chamada, não quando é definida. T: PartialOrd + Copy restringe T a tipos que podem ser comparados e copiados — exatamente o que largest precisa para funcionar, e nada mais.
fn largest<T: PartialOrd + Copy>(items: &[T]) -> T {
let mut largest = items[0];
for &item in items {
if item > largest {
largest = item;
}
}
largest
}
fn main() {
let numbers = vec![10, 25, 3, 47, 8];
println!("largest number: {}", largest(&numbers));
let chars = vec!['y', 'm', 'a', 'q'];
println!("largest char: {}", largest(&chars));
}largest number: 47 largest char: y
Structs genéricos
Structs também podem ser genéricos — Point<T> funciona para qualquer tipo T, com ambos os campos compartilhando o mesmo tipo. O próprio bound T: std::fmt::Display do bloco impl se aplica só a describe, então Point em si continua usável mesmo com tipos que não podem ser exibidos (displayed).
struct Point<T> {
x: T,
y: T,
}
impl<T: std::fmt::Display> Point<T> {
fn describe(&self) -> String {
format!("({}, {})", self.x, self.y)
}
}
fn main() {
let int_point = Point { x: 3, y: 4 };
let float_point = Point { x: 1.5, y: 2.5 };
println!("{}", int_point.describe());
println!("{}", float_point.describe());
}(3, 4) (1.5, 2.5)
Próximo: tratamento de erros — propagar um Result com ?, e escrever um tipo de erro personalizado.
Practice Exercise
Escreva uma função genérica first<T: Copy>(items: &[T]) -> T que retorne o primeiro item de um slice, depois imprima first(&[10, 20, 30]).