Skip to content

Commit

Permalink
fix(content:traits): move topics
Browse files Browse the repository at this point in the history
  • Loading branch information
SergioRibera committed Jan 7, 2025
1 parent fd61fd7 commit e8d905e
Show file tree
Hide file tree
Showing 5 changed files with 295 additions and 115 deletions.
75 changes: 37 additions & 38 deletions content/5.traits/definition.md → content/5.traits/1.definition.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,26 @@
---
title: 'Definiendo un Trait'
description: 'Definiendo Traits en Rust: La Base de la Abstracción y el Comportamiento'
title: "Definiendo un Trait"
description: "Definiendo Traits en Rust: La Base de la Abstracción y el Comportamiento"
draft: true
data:
type: 'custom'
topicLevel: 'start'
type: "custom"
topicLevel: "start"
position:
x: 200
x: 400
y: 900
sourcePosition:
cargo: 'top'
targetPosition:
smart-pointers: 'bottom'
traits: "left"
---

# Definiendo Traits en Rust: La Base de la Abstracción y el Comportamiento

En el artículo anterior, exploramos qué son los traits en Rust a nivel conceptual. Ahora vamos un paso más allá y nos enfocamos en **cómo definir y usar traits**. Veremos cómo incluir tipos y constantes dentro de ellos, cómo permitir que los traits se autoimplementen para ciertos tipos, y cómo separar lógicas en traits para lograr un diseño más modular.
En el artículo anterior, exploramos qué son los traits en Rust a nivel conceptual. Ahora vamos un paso más allá y nos enfocamos en **cómo definir y usar traits**. Veremos cómo incluir tipos y constantes dentro de ellos, cómo permitir que los traits se autoimplementen para ciertos tipos, y cómo separar lógicas en traits para lograr un diseño más modular.

## ¿Qué es un trait y cómo se define?
## ¿Qué es un trait y cómo se define?

Un **trait** en Rust se define utilizando la palabra clave `trait`. Dentro del trait, declaramos métodos que los tipos que lo implementen deben cumplir.
Un **trait** en Rust se define utilizando la palabra clave `trait`. Dentro del trait, declaramos métodos que los tipos que lo implementen deben cumplir.

### Ejemplo básico
### Ejemplo básico

```rust
trait Greeting {
Expand All @@ -42,9 +41,9 @@ let user = Person { name: "Alice".to_string() };
user.say_hello(); // Output: Hello, my name is Alice
```

## Métodos con implementación por defecto
## Métodos con implementación por defecto

Rust permite definir métodos con una implementación predeterminada en un trait. Esto significa que cualquier tipo que implemente el trait puede optar por usar la implementación predeterminada o proporcionar la suya propia.
Rust permite definir métodos con una implementación predeterminada en un trait. Esto significa que cualquier tipo que implemente el trait puede optar por usar la implementación predeterminada o proporcionar la suya propia.

```rust
trait Greeting {
Expand All @@ -61,11 +60,11 @@ let bot = Robot;
bot.say_hello(); // Output: Hello!
```

Esto es útil para reducir duplicación de código y proporcionar un comportamiento genérico.
Esto es útil para reducir duplicación de código y proporcionar un comportamiento genérico.

## Constantes en los traits
## Constantes en los traits

Los traits también pueden contener constantes. Estas constantes deben ser definidas en las implementaciones del trait.
Los traits también pueden contener constantes. Estas constantes deben ser definidas en las implementaciones del trait.

```rust
trait Configurable {
Expand All @@ -86,9 +85,9 @@ let net = Network;
println!("Max retries: {}", net.retries_allowed()); // Output: Max retries: 3
```

## Tipos asociados en los traits
## Tipos asociados en los traits

Los traits pueden definir **tipos asociados**. Esto permite que los tipos que implementen el trait especifiquen un tipo concreto para ese asociado.
Los traits pueden definir **tipos asociados**. Esto permite que los tipos que implementen el trait especifiquen un tipo concreto para ese asociado.

```rust
trait Container {
Expand Down Expand Up @@ -119,13 +118,13 @@ bag.add(4);
println!("{:?}", bag.remove()); // Output: Some(4)
```

Los tipos asociados hacen que el diseño sea más flexible y expresivo, especialmente cuando trabajamos con genéricos.
Los tipos asociados hacen que el diseño sea más flexible y expresivo, especialmente cuando trabajamos con genéricos.

## Autoimplementación de traits
## Autoimplementación de traits

Podemos crear traits que se implementen automáticamente para ciertos tipos o bajo condiciones específicas. Esto se conoce como **implementación en bloque blanket**.
Podemos crear traits que se implementen automáticamente para ciertos tipos o bajo condiciones específicas. Esto se conoce como **implementación en bloque blanket**.

### Ejemplo: Implementación para todos los tipos que cumplen un trait
### Ejemplo: Implementación para todos los tipos que cumplen un trait

```rust
trait Printable {
Expand All @@ -142,13 +141,13 @@ impl<T: std::fmt::Display> Printable for T {
"Hello, Rust!".print(); // Output: Hello, Rust!
```

Aquí, cualquier tipo que implemente `Display` también implementará automáticamente `Printable`.
Aquí, cualquier tipo que implemente `Display` también implementará automáticamente `Printable`.

## Separando lógicas con traits
## Separando lógicas con traits

Los traits nos permiten dividir la lógica de un programa en unidades pequeñas y reutilizables. Esto es especialmente útil en programas complejos.
Los traits nos permiten dividir la lógica de un programa en unidades pequeñas y reutilizables. Esto es especialmente útil en programas complejos.

### Ejemplo: Modularidad con múltiples traits
### Ejemplo: Modularidad con múltiples traits

```rust
trait Flyable {
Expand Down Expand Up @@ -178,11 +177,11 @@ sparrow.fly(); // Output: I can fly!
goldfish.swim(); // Output: I can swim!
```

Al separar los comportamientos en traits, puedes combinarlos fácilmente según sea necesario.
Al separar los comportamientos en traits, puedes combinarlos fácilmente según sea necesario.

## Implementaciones condicionales
## Implementaciones condicionales

Los traits pueden implementarse bajo ciertas condiciones utilizando el sistema de bounds genéricos de Rust.
Los traits pueden implementarse bajo ciertas condiciones utilizando el sistema de bounds genéricos de Rust.

```rust
trait Summable {
Expand All @@ -202,17 +201,17 @@ let numbers: Vec<i32> = vec![1, 2, 3];
println!("Sum: {}", numbers.sum()); // Output: Sum: 6
```

Esta implementación solo es válida si los elementos del `Vec` cumplen con las condiciones establecidas.
Esta implementación solo es válida si los elementos del `Vec` cumplen con las condiciones establecidas.

## Ventajas del diseño con traits
## Ventajas del diseño con traits

1. **Modularidad**: Los traits permiten dividir grandes problemas en piezas pequeñas y manejables.
2. **Reutilización de código**: Implementar comportamientos comunes en múltiples tipos.
3. **Abstracción poderosa**: Combinados con genéricos, los traits eliminan la necesidad de duplicar código para diferentes tipos.
4. **Extensibilidad**: Puedes añadir comportamientos a tipos existentes sin modificar su definición original.
1. **Modularidad**: Los traits permiten dividir grandes problemas en piezas pequeñas y manejables.
2. **Reutilización de código**: Implementar comportamientos comunes en múltiples tipos.
3. **Abstracción poderosa**: Combinados con genéricos, los traits eliminan la necesidad de duplicar código para diferentes tipos.
4. **Extensibilidad**: Puedes añadir comportamientos a tipos existentes sin modificar su definición original.

## Conclusión
## Conclusión

Los traits en Rust son una herramienta increíblemente poderosa para modelar comportamientos, separar lógicas y extender la funcionalidad de los tipos. Desde métodos con implementación por defecto hasta constantes y tipos asociados, los traits ofrecen flexibilidad para diseñar sistemas robustos y reutilizables.
Los traits en Rust son una herramienta increíblemente poderosa para modelar comportamientos, separar lógicas y extender la funcionalidad de los tipos. Desde métodos con implementación por defecto hasta constantes y tipos asociados, los traits ofrecen flexibilidad para diseñar sistemas robustos y reutilizables.

Al comprender cómo funcionan y cómo podemos aprovecharlos para estructurar programas de manera más eficiente, estaremos mejor equipados para aprovechar todo el potencial que Rust tiene para ofrecer. 🚀
45 changes: 21 additions & 24 deletions content/5.traits/autotraits.md → content/5.traits/2.autotraits.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
---
title: 'Autotraits'
description: 'Explorando los Auto Traits y Autoimplementaciones en Rust'
title: "Autotraits"
description: "Explorando los Auto Traits y Autoimplementaciones en Rust"
draft: true
data:
type: 'custom'
topicLevel: 'start'
type: "custom"
topicLevel: "start"
position:
x: 200
y: 900
sourcePosition:
cargo: 'top'
targetPosition:
smart-pointers: 'bottom'
x: 400
y: 940
---

# Explorando los Auto Traits y Autoimplementaciones en Rust

Rust ofrece un sistema de tipos poderoso y flexible que facilita la abstracción, reutilización y seguridad. Entre sus características avanzadas, encontramos los **auto traits** y la posibilidad de realizar **autoimplementaciones** para genéricos y genéricos que cumplen ciertas condiciones (bounds). Estas herramientas permiten escribir código más expresivo y conciso, y son fundamentales para construir bibliotecas y aplicaciones robustas. En este post, exploraremos ambos temas a fondo.
Expand Down Expand Up @@ -44,7 +41,7 @@ Aquí, `Send` asegura que los datos pueden moverse de manera segura entre hilos.

### Creando Auto Traits

Aunque la mayoría de los auto traits relevantes ya están definidos en la biblioteca estándar (por ejemplo, `Send` y `Sync`), puedes crear los tuyos propios usando la palabra clave `unsafe auto trait`.
Aunque la mayoría de los auto traits relevantes ya están definidos en la biblioteca estándar (por ejemplo, `Send` y `Sync`), puedes crear los tuyos propios usando la palabra clave `unsafe auto trait`.

```rust
unsafe auto trait MyAutoTrait {}
Expand Down Expand Up @@ -103,17 +100,17 @@ let numbers: Vec<i32> = vec![1, 2, 3];
println!("Sum: {}", numbers.sum()); // Output: Sum: 6
```

En este ejemplo, la implementación del trait `Summable` para `Vec<T>` solo es válida si el tipo `T` cumple con:
En este ejemplo, la implementación del trait `Summable` para `Vec<T>` solo es válida si el tipo `T` cumple con:

1. Implementar el operador `Add`.
2. Ser `Copy`.
3. Convertirse en `i32` mediante `Into<i32>`.
1. Implementar el operador `Add`.
2. Ser `Copy`.
3. Convertirse en `i32` mediante `Into<i32>`.

Esto permite construir implementaciones robustas y seguras que aprovechan las capacidades del sistema de tipos de Rust.

## Uso Avanzado: Implementaciones Recursivas con Genéricos
## Uso Avanzado: Implementaciones Recursivas con Genéricos

Las autoimplementaciones también se pueden utilizar para construir jerarquías de comportamiento que se basan en el sistema de tipos de Rust.
Las autoimplementaciones también se pueden utilizar para construir jerarquías de comportamiento que se basan en el sistema de tipos de Rust.

```rust
trait Flattenable {
Expand All @@ -140,15 +137,15 @@ println!("{:?}", flattened); // Output: [1, 2, 3, 4]

Aquí, usamos bounds genéricos para implementar un comportamiento de "aplanado" (`flatten`) para vectores de elementos que implementan `IntoIterator`. Esto permite extender la funcionalidad del tipo sin modificar su definición.

## Beneficios del Sistema de Auto Traits y Autoimplementaciones
## Beneficios del Sistema de Auto Traits y Autoimplementaciones

1. **Código Reutilizable**: Puedes definir comportamiento genérico que se aplica a múltiples tipos sin duplicar código.
2. **Seguridad Garantizada por el Compilador**: Los bounds genéricos aseguran que las implementaciones solo se apliquen a tipos válidos.
3. **Extensibilidad**: Puedes extender tipos existentes con nuevas funcionalidades sin acceso a su código fuente.
4. **Eficiencia**: Al permitir que el compilador maneje las implementaciones automáticas, se reduce el riesgo de errores y se mejora la mantenibilidad.
1. **Código Reutilizable**: Puedes definir comportamiento genérico que se aplica a múltiples tipos sin duplicar código.
2. **Seguridad Garantizada por el Compilador**: Los bounds genéricos aseguran que las implementaciones solo se apliquen a tipos válidos.
3. **Extensibilidad**: Puedes extender tipos existentes con nuevas funcionalidades sin acceso a su código fuente.
4. **Eficiencia**: Al permitir que el compilador maneje las implementaciones automáticas, se reduce el riesgo de errores y se mejora la mantenibilidad.

## Conclusión
## Conclusión

Los auto traits y las autoimplementaciones para genéricos son herramientas clave en Rust que permiten aprovechar al máximo su sistema de tipos. Los auto traits, como `Send` y `Sync`, garantizan la seguridad en entornos concurrentes, mientras que las autoimplementaciones hacen que los traits sean más flexibles y reutilizables.
Los auto traits y las autoimplementaciones para genéricos son herramientas clave en Rust que permiten aprovechar al máximo su sistema de tipos. Los auto traits, como `Send` y `Sync`, garantizan la seguridad en entornos concurrentes, mientras que las autoimplementaciones hacen que los traits sean más flexibles y reutilizables.

Con estas herramientas, puedes escribir programas más expresivos y seguros, al tiempo que reduces la complejidad del código. Dominar estas características te permitirá crear bibliotecas y aplicaciones que aprovechen todo el potencial de Rust. 🚀
51 changes: 34 additions & 17 deletions content/5.traits/integrated.md → content/5.traits/3.integrated.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
---
title: 'Traits Integrados'
description: 'Entendiendo los Traits Más Importantes en Rust'
title: "Traits Integrados"
description: "Entendiendo los Traits Más Importantes en Rust"
draft: true
data:
type: 'custom'
topicLevel: 'start'
type: "custom"
topicLevel: "start"
position:
x: 200
y: 900
sourcePosition:
cargo: 'top'
targetPosition:
smart-pointers: 'bottom'
x: 400
y: 980
---

### Entendiendo los Traits Más Importantes en Rust

Rust incluye una rica colección de *traits* estándar que permiten a los tipos integrarse con el lenguaje y aprovechar comportamientos reutilizables. Estos *traits* son contratos que los tipos pueden implementar para adquirir funcionalidades específicas. Aquí exploraremos algunos de los más importantes, explicando sus conceptos y cómo aplicarlos.
Rust incluye una rica colección de _traits_ estándar que permiten a los tipos integrarse con el lenguaje y aprovechar comportamientos reutilizables. Estos _traits_ son contratos que los tipos pueden implementar para adquirir funcionalidades específicas. Aquí exploraremos algunos de los más importantes, explicando sus conceptos y cómo aplicarlos.

### **1. El Trait `Default`: Valores Predeterminados**

El trait `Default` define un método para crear un valor predeterminado para un tipo. Esto es especialmente útil al inicializar estructuras grandes con valores predecibles.

#### Definición

```rust
pub trait Default {
fn default() -> Self;
}
```

#### Ejemplo

```rust
struct Config {
retries: u32,
Expand All @@ -50,10 +50,12 @@ fn main() {
```

### **2. Los Traits `Clone` y `Copy`: Clonación y Copia**

- **`Clone`**: Proporciona un método explícito para crear una copia profunda de un valor.
- **`Copy`**: Es una versión implícita y más ligera de clonación, aplicable solo a tipos que se pueden copiar de manera trivial (como números primitivos).

#### Definición

```rust
pub trait Clone {
fn clone(&self) -> Self;
Expand All @@ -63,6 +65,7 @@ pub trait Copy: Clone {}
```

#### Ejemplo

```rust
#[derive(Clone, Copy)]
struct Point {
Expand All @@ -79,14 +82,18 @@ fn main() {
```

#### Nota sobre `Copy`

Un tipo que implementa `Copy` no puede tener campos que no lo implementen.

### **3. Comparación: `PartialEq` y `Eq`**

Rust proporciona dos traits para comparar tipos:

- **`PartialEq`**: Permite verificar si dos valores son iguales (`==`) o diferentes (`!=`).
- **`Eq`**: Es un subtipo de `PartialEq` que asegura que el operador `==` siempre sea reflexivo (es decir, `a == a` siempre es verdadero).

#### Ejemplo

```rust
#[derive(PartialEq, Eq)]
struct User {
Expand All @@ -105,10 +112,12 @@ fn main() {
```

### **4. Ordenamiento: `PartialOrd` y `Ord`**

- **`PartialOrd`**: Permite comparar valores con `<`, `>`, `<=`, `>=`.
- **`Ord`**: Extiende `PartialOrd` para tipos totalmente ordenables.

#### Ejemplo

```rust
#[derive(PartialOrd, Ord, PartialEq, Eq)]
struct Item {
Expand All @@ -126,13 +135,15 @@ fn main() {
```

### **5. Traits de Funciones: `Fn`, `FnMut` y `FnOnce`**
Estos traits representan diferentes tipos de clausuras (*closures*).

- **`FnOnce`**: Consumo único.
- **`FnMut`**: Clausura mutable.
Estos traits representan diferentes tipos de clausuras (_closures_).

- **`FnOnce`**: Consumo único.
- **`FnMut`**: Clausura mutable.
- **`Fn`**: Clausura inmutable.

#### Ejemplo

```rust
fn execute<F>(operation: F)
where
Expand All @@ -147,10 +158,12 @@ fn main() {
}
```

### **6. El Trait `Drop`: Limpiar Recursos**
### **6. El Trait `Drop`: Limpiar Recursos**

Permite ejecutar lógica personalizada cuando un valor sale de alcance.

#### Ejemplo

```rust
struct Resource {
name: String,
Expand All @@ -167,10 +180,12 @@ fn main() {
} // `_res` se libera aquí automáticamente.
```

### **7. Iteradores: `Iterator`**
### **7. Iteradores: `Iterator`**

El trait `Iterator` es fundamental para trabajar con iteraciones. Define cómo un tipo produce una secuencia de valores.

#### Definición

```rust
pub trait Iterator {
type Item;
Expand All @@ -179,6 +194,7 @@ pub trait Iterator {
```

#### Ejemplo

```rust
struct Counter {
count: u32,
Expand All @@ -205,5 +221,6 @@ fn main() {
}
```

### **Conclusión**
### **Conclusión**

Estos traits estándar son esenciales en Rust, ya que forman la base para operaciones comunes como clonación, comparación, iteración y manejo de recursos. Entender cómo y cuándo usarlos es clave para aprovechar todo el potencial de Rust y escribir código más limpio, seguro y eficiente.
Loading

0 comments on commit e8d905e

Please sign in to comment.