es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Trae la sobrecarga de función (a través de un rasgo) al alcance.

Estoy tratando de sobrecargar las funciones miembro de mi clase (similar a lo que se puede hacer en C ++). Así que leí que en Rust se debe usar traits para lograr esto. A continuación se muestra un código de muestra (nota: esto es solo para demostrar la idea):

/* my_class.rs */
pub struct MyClass {
    pub a: i32,
    pub b: i32,
}

pub trait Func<t> {
    fn func(&self, t: T) -> Self;
}

impl Func<i32> for MyClass {
    fn func(&self, t: i32) -> MyClass {
        MyClass {
            a: self.a + t,
            b: self.b,
        }
    }
}

impl Func<&str> for MyClass {
    fn func(&self, t: &str) -> MyClass {
        MyClass {
            a: self.a,
            b: self.b + t.parse::<i32>().unwrap(),
        }
    }
}

y

/* main.rs */
mod my_class;
use crate::my_class::MyClass;
use crate::my_class::Func;

fn main() {
    let m1 = MyClass { a: 10, b: 20 }.func(5);
    let m2 = MyClass { a: 10, b: 20 }.func("-8");
    println!("a={}, b={}", m1.a, m1.b);
    println!("a={}, b={}", m2.a, m2.b);
}

En primer lugar, ¿es esta la forma correcta de sobrecargar las funciones miembro de una clase? Parece un poco engorroso, ya que uno necesita agregar la plantilla de pub trait Func para cada sobrecarga de función.

Y en segundo lugar, ¿existe alguna forma para que no tenga que escribir use crate::my_class::Func; para cada trait? Es decir, ¿cómo puedo traer todas las funciones de MyClass (tanto las definidas a través de impl MyClass como impl Func for MyClass) al alcance cuando importo MyClass?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Sobrecarga de funciones miembro en Rust usando Traits

    Rust no admite la sobrecarga de métodos tradicional como C++, pero proporciona un enfoque alternativo usando Traits. Un Trait puede ser utilizado para definir un conjunto de métodos, y luego puede ser implementado para diferentes tipos para proporcionar una implementación diferente de estos métodos.

    El código de ejemplo proporcionado en la pregunta es una forma de lograr la sobrecarga en Rust usando Traits. La estructura MyClass implementa el Trait Func<t> para diferentes tipos de T. Esto permite llamar el método func con diferentes argumentos de tipo T.

    pub trait Func<t> {
        fn func(&self, t: T) -> Self;
    }
    

    Mejorando la sobrecarga de métodos

    El enfoque de definir un nuevo Trait para cada sobrecarga de método puede ser engorroso, especialmente si la clase tiene muchos métodos. Un enfoque mejor es definir un solo Trait con múltiples métodos e implementarlo para la estructura.

    pub trait MyTrait {
        fn method1(&self, arg1: i32) -> Self;
        fn method2(&self, arg1: &str) -> Self;
        // añadir más métodos aquí
    }
    
    impl MyTrait for MyClass {
        fn method1(&self, arg1: i32) -> Self {
            MyClass { a: self.a + arg1, b: self.b }
        }
    
        fn method2(&self, arg1: &str) -> Self {
            MyClass { a: self.a, b: self.b + arg1.parse::<i32>().unwrap() }
        }
        // implementar más métodos aquí
    }
    

    De esta manera, definimos nuestro propio Trait e implementamos para MyClass. Ahora podemos llamar varios métodos usando una referencia al objeto MyClass.

    let m1 = MyClass {a: 10, b:20}.method1(5).method2("-8");
    

    Trayendo métodos al ámbito

    Para llevar todos los métodos de MyClass al ámbito cuando importamos MyClass, podemos usar la instrucción use con un patrón de comodín.

    /* main.rs */
    mod my_class;
    use crate::my_class::{MyClass, MyTrait};
    
    fn main() {
        let m1 = MyClass {a: 10, b:20}.method1(5).method2("-8");
        // los métodos de MyTrait también están disponibles
        let m2 = MyClass {a: 10, b:20}.method3();
        println!("a={}, b={}", m1.a, m1.b);
        println!("a={}, b={}", m2.a, m2.b);
    }
    

    Al usar la instrucción use crate::my_class::{MyClass, MyTrait};, traemos tanto MyClass como MyTrait al ámbito, y todos sus métodos pueden ser utilizados sin ningún prefijo de calificación.

Comments are closed.