Problema al utilizar traits en Rust

Publicado por Brisa
hace 4 meses

Hola a todos,

Estoy teniendo un problema al utilizar traits en Rust. Estoy intentando definir una interfaz común para varios tipos de objetos, pero no puedo implementar métodos específicos para cada tipo de objeto. Aquí está el código:

trait Dibujable {
    fn dibujar(&self);
    fn obtener_area(&self) -> f64;
}

struct Rectangulo {
    ancho: f64,
    alto: f64,
}

impl Dibujable for Rectangulo {
    fn dibujar(&self) {
        println!("Dibujando un rectángulo");
    }
}

impl Rectangulo {
    fn obtener_perimetro(&self) -> f64 {
        2.0 * (self.ancho + self.alto)
    }
}

El problema está en la implementación del método obtener_perimetro() para el struct Rectangulo. Rust me está dando el siguiente error:

error: no method named `obtener_perimetro` found for reference `&Rectangulo` in the current scope

Entiendo que el problema es que el método obtener_perimetro() no está definido en el trait Dibujable, pero ¿cómo puedo solucionar esto sin tener que añadir el método a todos los structs que implementan Dibujable?

Gracias de antemano por su ayuda.

traits herencia implementación de métodos
Respuesta de Gordon Shumway
hace 4 meses

¡Hola Brisa!

El error que te muestra Rust indica que estás tratando de llamar al método obtener_perimetro en un contexto en el que Rust espera que se llame a través de una referencia a Rectangulo que implemente el trait Dibujable, pero ese método no está definido en el trait.

Para solucionar esto, puedes llamar directamente al método obtener_perimetro en una instancia de Rectangulo, ya que este método es específico para la struct Rectangulo y no es parte del trait Dibujable. Aquí hay un ejemplo de cómo podrías hacer uso del método obtener_perimetro:

fn main() {
    let rect = Rectangulo {
        ancho: 10.0,
        alto: 5.0,
    };

    rect.dibujar(); // Okay, porque `dibujar` es un método de `Dibujable`.
    println!("Área: {}", rect.obtener_area()); // Okay, también parte de `Dibujable`.
    println!("Perímetro: {}", rect.obtener_perimetro()); // Okay, porque estamos llamando directamente en `Rectangulo`.
}

Asumiendo que incluyas la implementación faltante de obtener_area para Rectangulo, el código anterior debería funcionar sin problemas. Si deseas poder llamar a obtener_perimetro en un contexto donde solo sabes que tienes algo que implementa Dibujable, entonces tendrás que considerar usar algún enfoque de despacho dinámico como Box<dyn Dibujable> y downcasting, o reestructurar tus traits y structs para reflejar de alguna manera esa funcionalidad necesaria, lo cual podría agregar complejidad no deseada.

Recuerda que esto último solo deberías considerarlo si realmente necesitas tratar a obtener_perimetro como una operación polimórfica en el contexto de varios tipos que implementan Dibujable.

Espero que esto aclare tus dudas y que puedas seguir adelante con tu proyecto en Rust. ¡Mucho ánimo!