ProgramaciónDesarrollador de Rust / Desarrollador Backend

¿Qué son los constructores y métodos de fábrica en Rust (por ejemplo, new, with_capacity), cómo implementarlos correctamente y qué errores cometen los principiantes?

Supere entrevistas con el asistente de IA Hintsage

Respuesta.

Rust no tiene constructores especiales como, por ejemplo, en C++/Java. Normalmente, un constructor se implementa como una función asociada (por ejemplo, new). Características importantes:

  • La función asociada no está relacionada con traits u objetos, se llama a través de ::.
  • Puede devolver tanto self como Result<Self, E> — útil para constructores que pueden fallar.
  • Se pueden implementar diferentes fábricas (with_capacity, from_str, variantes personalizadas).

Ejemplo de un constructor básico:

struct Point { x: i32, y: i32 } impl Point { pub fn new(x: i32, y: i32) -> Self { Point { x, y } } }

Ejemplo de un constructor que puede fallar:

impl Point { pub fn try_new(x: i32, y: i32) -> Result<Self, String> { if x < 0 || y < 0 { Err("Las coordenadas deben ser no negativas".to_string()) } else { Ok(Point { x, y }) } } }

Pregunta trampa.

¿Qué tipo de función debe utilizarse para un constructor: función normal, método o función asociada, y por qué?

Muchos responden: "método". Pero en Rust los constructores son solo funciones asociadas (sin self), ya que el ejemplar aún no existe y no se puede llamar a un método normal.

struct Foo; impl Foo { // función asociada, no método pub fn new() -> Self { Foo } }

Ejemplos de errores reales debido al desconocimiento de los matices del tema.


Historia

Un programador implementó el constructor como método:

impl Point { pub fn make(&self, x: i32, y: i32) -> Self { ... } }

Esto es ilógico y confunde: ¡se necesita un objeto para crear un objeto que aún no existe! El desarrollador se perdió sobre cómo llamar a este método. Se corrigió a una función estática.


Historia

Error clásico: devolver Option<Self> para un constructor fallido sin advertencia, lo que provoca omitir errores en cascada. Después de regresar a Result<Self, E>, se volvió posible mostrar los errores de manera más explícita.


Historia

Implementación de fábricas como from_parts, from_str sin el uso del trait From/FromStr. Como resultado, no funcionaron los mecanismos estándar de conversiones (por ejemplo, str.parse::<MyType>()). Después de detectar el error, se incorporó FromStr y se mejoró la compatibilidad del código con las bibliotecas de la ecosistema.