Explorando los Tipos Asociados de Rust

RustRustBeginner
Practicar Ahora

This tutorial is from open-source community. Access the source code

💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí

Introducción

En este laboratorio, exploramos el concepto de tipos asociados en Rust, que permite mejorar la legibilidad del código al definir tipos internos localmente dentro de un trato como tipos de salida. Esto se logra mediante el uso de la palabra clave type dentro de la definición del trato. Con tipos asociados, las funciones que usan el trato ya no necesitan expresar explícitamente los tipos A y B, lo que hace que el código sea más conciso y flexible. Reescribimos un ejemplo de la sección anterior usando tipos asociados para ilustrar su uso en la práctica.

Nota: Si el laboratorio no especifica un nombre de archivo, puede usar cualquier nombre de archivo que desee. Por ejemplo, puede usar main.rs, compilar y ejecutarlo con rustc main.rs &&./main.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL rust(("Rust")) -.-> rust/BasicConceptsGroup(["Basic Concepts"]) rust(("Rust")) -.-> rust/DataTypesGroup(["Data Types"]) rust(("Rust")) -.-> rust/FunctionsandClosuresGroup(["Functions and Closures"]) rust(("Rust")) -.-> rust/DataStructuresandEnumsGroup(["Data Structures and Enums"]) rust(("Rust")) -.-> rust/AdvancedTopicsGroup(["Advanced Topics"]) rust/BasicConceptsGroup -.-> rust/variable_declarations("Variable Declarations") rust/DataTypesGroup -.-> rust/integer_types("Integer Types") rust/DataTypesGroup -.-> rust/type_casting("Type Conversion and Casting") rust/FunctionsandClosuresGroup -.-> rust/function_syntax("Function Syntax") rust/FunctionsandClosuresGroup -.-> rust/expressions_statements("Expressions and Statements") rust/DataStructuresandEnumsGroup -.-> rust/method_syntax("Method Syntax") rust/AdvancedTopicsGroup -.-> rust/traits("Traits") rust/AdvancedTopicsGroup -.-> rust/operator_overloading("Traits for Operator Overloading") subgraph Lab Skills rust/variable_declarations -.-> lab-99354{{"Explorando los Tipos Asociados de Rust"}} rust/integer_types -.-> lab-99354{{"Explorando los Tipos Asociados de Rust"}} rust/type_casting -.-> lab-99354{{"Explorando los Tipos Asociados de Rust"}} rust/function_syntax -.-> lab-99354{{"Explorando los Tipos Asociados de Rust"}} rust/expressions_statements -.-> lab-99354{{"Explorando los Tipos Asociados de Rust"}} rust/method_syntax -.-> lab-99354{{"Explorando los Tipos Asociados de Rust"}} rust/traits -.-> lab-99354{{"Explorando los Tipos Asociados de Rust"}} rust/operator_overloading -.-> lab-99354{{"Explorando los Tipos Asociados de Rust"}} end

Tipos asociados

El uso de "Tipos asociados" mejora la legibilidad general del código al mover los tipos internos localmente a un trato como tipos de salida. La sintaxis para la definición del trato es la siguiente:

// `A` y `B` se definen en el trato a través de la palabra clave `type`.
// (Nota: `type` en este contexto es diferente de `type` cuando se utiliza
// para alias).
trait Contains {
    type A;
    type B;

    // Sintaxis actualizada para referirse a estos nuevos tipos de manera genérica.
    fn contains(&self, _: &Self::A, _: &Self::B) -> bool;
}

Tenga en cuenta que las funciones que usan el trato Contains ya no se requiere expresar A o B en absoluto:

// Sin usar tipos asociados
fn difference<A, B, C>(container: &C) -> i32 where
    C: Contains<A, B> {... }

// Usando tipos asociados
fn difference<C: Contains>(container: &C) -> i32 {... }

Vamos a reescribir el ejemplo de la sección anterior usando tipos asociados:

struct Container(i32, i32);

// Un trato que verifica si 2 elementos se almacenan dentro del contenedor.
// También recupera el primer o último valor.
trait Contains {
    // Defina tipos genéricos aquí que los métodos podrán utilizar.
    type A;
    type B;

    fn contains(&self, _: &Self::A, _: &Self::B) -> bool;
    fn first(&self) -> i32;
    fn last(&self) -> i32;
}

impl Contains for Container {
    // Especifique qué tipos son `A` y `B`. Si el tipo `input`
    // es `Container(i32, i32)`, los tipos `output` se determinan
    // como `i32` e `i32`.
    type A = i32;
    type B = i32;

    // `&Self::A` y `&Self::B` también son válidos aquí.
    fn contains(&self, number_1: &i32, number_2: &i32) -> bool {
        (&self.0 == number_1) && (&self.1 == number_2)
    }
    // Obtenga el primer número.
    fn first(&self) -> i32 { self.0 }

    // Obtenga el último número.
    fn last(&self) -> i32 { self.1 }
}

fn difference<C: Contains>(container: &C) -> i32 {
    container.last() - container.first()
}

fn main() {
    let number_1 = 3;
    let number_2 = 10;

    let container = Container(number_1, number_2);

    println!("¿Contiene el contenedor {} y {}: {}",
        &number_1, &number_2,
        container.contains(&number_1, &number_2));
    println!("Primer número: {}", container.first());
    println!("Último número: {}", container.last());

    println!("La diferencia es: {}", difference(&container));
}

Resumen

¡Felicidades! Has completado el laboratorio de Tipos Asociados. Puedes practicar más laboratorios en LabEx para mejorar tus habilidades.