Traits
## Objetivos de Aprendizaje
- Definir e implementar traits
- Usar limites de traits
- Implementaciones por defecto
- Dominar traits estandar comunes
- Trabajar con traits genericos
## Que son los Traits?
Los traits definen comportamiento compartido entre tipos:
```rust
trait Summary {
fn summarize(&self) -> String;
}
```
## Implementando Traits
### Implementacion Basica
```rust
trait Summary {
fn summarize(&self) -> String;
}
struct Article {
title: String,
author: String,
}
impl Summary for Article {
fn summarize(&self) -> String {
format!("{} by {}", self.title, self.author)
}
}
fn main() {
let article = Article {
title: String::from("Rust Tutorial"),
author: String::from("Alice"),
};
println!("{}", article.summarize());
}
```
### Multiples Traits
```rust
trait Summarize {
fn summarize(&self) -> String;
}
trait Printable {
fn print(&self);
}
struct Article {
title: String,
author: String,
}
impl Summarize for Article {
fn summarize(&self) -> String {
format!("{} by {}", self.title, self.author)
}
}
impl Printable for Article {
fn print(&self) {
println!("Title: {}\nAuthor: {}", self.title, self.author);
}
}
```
## Implementaciones por Defecto
```rust
trait Summary {
fn summarize(&self) -> String {
String::from("(Read more...)") // Implementacion por defecto
}
}
struct Tweet {
username: String,
content: String,
}
impl Summary for Tweet {
// Usa la implementacion por defecto de summarize
// O sobreescribir:
// fn summarize(&self) -> String {
// format!("@{}: {}", self.username, self.content)
// }
}
fn main() {
let tweet = Tweet {
username: String::from("alice"),
content: String::from("Hello world"),
};
println!("{}", tweet.summarize()); // (Read more...)
}
```
## Limites de Traits
### Sintaxis Basica
```rust
fn notify(item: &impl Summary) {
println!("Breaking news! {}", item.summarize());
}
```
### Sintaxis de Limite de Trait
```rust
fn notify(item: &T) {
println!("Breaking news! {}", item.summarize());
}
```
### Multiples Limites de Traits
```rust
fn notify(item: &(impl Summary + Display)) { }
fn notify(item: &T) { }
```
### Clausulas where
```rust
fn some_function(t: &T, u: &U)
where
T: Display + Clone,
U: Clone + Debug,
{
// ...
}
```
## Implementar Metodos Condicionalmente
```rust
use std::fmt::Display;
struct Pair {
x: T,
y: T,
}
impl Pair {
fn new(x: T, y: T) -> Self {
Self { x, y }
}
}
impl Pair {
fn cmp_display(&self) {
if self.x >= self.y {
println!("The largest member is x = {}", self.x);
} else {
println!("The largest member is y = {}", self.y);
}
}
}
```
## Devolviendo Tipos que Implementan Traits
```rust
trait Summary {
fn summarize(&self) -> String;
}
fn returns_summarizable() -> impl Summary {
Tweet {
username: String::from("alice"),
content: String::from("Hello"),
}
}
```
## Usando Limites de Traits para Metodos Condicionales
```rust
use std::fmt::Display;
struct Wrapper {
value: T,
}
impl Wrapper {
fn new(value: T) -> Self {
Wrapper { value }
}
}
impl Wrapper {
fn print(&self) {
println!("{}", self.value);
}
}
impl Wrapper {
fn eq(&self, other: &Wrapper) -> bool {
self.value == other.value
}
}
```
## Traits Estandar Comunes
### Debug
```rust
#[derive(Debug)]
struct Rectangle {
width: u32,
height: u32,
}
fn main() {
let rect = Rectangle { width: 30, height: 50 };
println!("{:?}", rect);
println!("{:#?}", rect);
}
```
### Clone y Copy
```rust
#[derive(Clone, Copy)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let p1 = Point { x: 1, y: 2 };
let p2 = p1; // Copia
let p3 = p1.clone(); // Clon
println!("{:?}", p1); // p1 sigue siendo valido (Copy)
}
```
### PartialEq y Eq
```rust
#[derive(PartialEq, Eq)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let p1 = Point { x: 1, y: 2 };
let p2 = Point { x: 1, y: 2 };
println!("{}", p1 == p2); // true
}
```
### PartialOrd y Ord
```rust
#[derive(PartialOrd, Ord)]
struct Person {
name: String,
age: u32,
}
fn main() {
let p1 = Person { name: "Alice".to_string(), age: 30 };
let p2 = Person { name: "Bob".to_string(), age: 25 };
println!("{}", p1 > p2); // true
}
```
### Display
```rust
use std::fmt;
struct Point {
x: i32,
y: i32,
}
impl fmt::Display for Point {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
fn main() {
let p = Point { x: 1, y: 2 };
println!("{}", p); // (1, 2)
}
```
### Default
```rust
#[derive(Default)]
struct Config {
width: u32,
height: u32,
name: String,
}
fn main() {
let config = Config {
width: 100,
..Default::default()
};
}
```
## Implementaciones Completas (Blanket Implementations)
Implementar trait para todos los tipos que satisfacen los limites:
```rust
use std::fmt::Display;
impl T {
fn print_twice(&self) {
println!("{}", self);
println!("{}", self);
}
}
fn main() {
42.print_twice();
}
```
## Supertraits
Requerir que un trait implemente otro trait:
```rust
use std::fmt::{Display, Debug};
trait OutlinePrint: Display {
fn outline_print(&self) {
let output = self.to_string();
let len = output.len();
println!("{}", "*".repeat(len + 4));
println!("* {} *", " ".repeat(len));
println!("* {} *", output);
println!("* {} *", " ".repeat(len));
println!("{}", "*".repeat(len + 4));
}
}
struct Point {
x: i32,
y: i32,
}
impl Display for Point {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
impl OutlinePrint for Point {}
```
## Resumen
- Los traits definen comportamiento compartido (como interfaces)
- Implementar traits con `impl TraitName for Type`
- Las implementaciones por defecto pueden ser sobreescritas
- Limites de traits: `impl Trait` o `T: Trait`
- Multiples limites: `T: Trait1 + Trait2`
- Clausulas where para limites complejos
- `impl Trait` para tipos de retorno
- Traits derive comunes: Debug, Clone, Copy, PartialEq, Eq, Default
- Implementaciones completas: `impl Trait for T`
Comments
Comments powered by Giscus
To enable comments, add your Giscus embed code here.
Learn more about Giscus →