Traits
Un trait define un conjunto de métodos que un tipo puede implementar — similar a una interface en otros lenguajes. Una vez que un tipo implementa un trait, puedes llamar a los métodos de ese trait directamente sobre él.
trait Greet {
fn greet(&self) -> String;
}
struct Person {
name: String,
}
impl Greet for Person {
fn greet(&self) -> String {
format!("Hello, my name is {}", self.name)
}
}
fn main() {
let alice = Person { name: String::from("Alice") };
println!("{}", alice.greet());
}Hello, my name is Alice
Trait bounds
Una función genérica puede exigir que su parámetro de tipo implemente un trait en particular, escrito como T: Greet. Esto permite que greet_everyone acepte un slice de cualquier tipo que implemente Greet, no solo Person específicamente — la función se escribe una sola vez y funciona para cualquier tipo que satisfaga el bound.
trait Greet {
fn greet(&self) -> String;
}
struct Person {
name: String,
}
impl Greet for Person {
fn greet(&self) -> String {
format!("Hello, my name is {}", self.name)
}
}
fn greet_everyone<T: Greet>(items: &[T]) {
for item in items {
println!("{}", item.greet());
}
}
fn main() {
let people = vec![
Person { name: String::from("Alice") },
Person { name: String::from("Bob") },
];
greet_everyone(&people);
}Hello, my name is Alice Hello, my name is Bob
Siguiente: generics — escribir una función o struct que funcione con muchos tipos, el mecanismo general sobre el que se construyen los trait bounds.
Practice Exercise
Define un trait Area con un método area(&self) -> f64. Impleméntalo para un struct Square { side: f64 } de modo que area() devuelva side * side. Crea un Square con side 4.0 e imprime su area().