Rust: Estructuras de datos
Descubre cómo crear y manejar estructuras de datos en Rust para organizar y optimizar tu código con ejemplos claros y conceptos esenciales.
Aprende Rust GRATIS y certifícateEstructuras de datos en Rust
Las estructuras de datos constituyen el fundamento sobre el cual construimos aplicaciones eficientes y organizadas. En Rust, estas herramientas nos permiten agrupar información relacionada de manera coherente, facilitando tanto la comprensión del código como su mantenimiento a largo plazo.
Fundamentos conceptuales
Una estructura de datos representa una forma de organizar y almacenar información que refleja las relaciones naturales entre diferentes elementos de nuestro dominio. En el contexto de Rust, las estructuras nos proporcionan un mecanismo para crear tipos personalizados que encapsulan datos relacionados bajo una única entidad lógica.
La sintaxis básica para definir una estructura en Rust utiliza la palabra clave struct
, seguida del nombre de la estructura y la definición de sus campos:
struct Usuario {
nombre: String,
edad: u32,
activo: bool,
}
Esta definición establece un nuevo tipo llamado Usuario
que agrupa tres campos diferentes, cada uno con su tipo específico. La declaración de tipos en cada campo garantiza la seguridad de memoria característica de Rust.
Creación e inicialización
Para crear una instancia de una estructura, especificamos valores para todos sus campos utilizando una sintaxis similar a la definición:
let usuario1 = Usuario {
nombre: String::from("Ana García"),
edad: 28,
activo: true,
};
Rust también permite la inicialización abreviada cuando las variables locales tienen el mismo nombre que los campos de la estructura:
fn crear_usuario(nombre: String, edad: u32) -> Usuario {
Usuario {
nombre, // equivale a nombre: nombre
edad, // equivale a edad: edad
activo: true,
}
}
Acceso y modificación de campos
El acceso a los campos se realiza mediante la notación de punto, permitiendo tanto lectura como escritura cuando la instancia es mutable:
let mut usuario = Usuario {
nombre: String::from("Carlos López"),
edad: 35,
activo: false,
};
println!("Nombre: {}", usuario.nombre);
usuario.edad = 36; // Modificación permitida por ser mutable
La mutabilidad en Rust se aplica a toda la instancia, no a campos individuales. Esto significa que una estructura es completamente mutable o completamente inmutable.
Sintaxis de actualización
Rust proporciona una sintaxis de actualización que facilita la creación de nuevas instancias basadas en instancias existentes:
let usuario2 = Usuario {
nombre: String::from("María Rodríguez"),
..usuario1 // Copia los campos restantes de usuario1
};
Esta característica resulta especialmente útil cuando necesitamos crear variaciones de estructuras existentes modificando solo algunos campos específicos.
Estructuras tupla
Las estructuras tupla ofrecen una alternativa cuando necesitamos agrupar datos pero los nombres de los campos no aportan valor semántico significativo:
struct Coordenadas(f64, f64, f64);
struct Color(u8, u8, u8);
let punto = Coordenadas(10.5, 20.3, 15.7);
let rojo = Color(255, 0, 0);
El acceso a los elementos en estructuras tupla utiliza índices numéricos:
println!("Coordenada X: {}", punto.0);
println!("Componente rojo: {}", rojo.0);
Estructuras unitarias
Las estructuras unitarias no contienen datos pero pueden implementar traits, resultando útiles para crear tipos que representen conceptos sin estado asociado:
struct Marcador;
let instancia = Marcador;
Ownership y borrowing en estructuras
El sistema de ownership de Rust se aplica de manera integral a las estructuras. Cuando una estructura contiene tipos que implementan el trait Copy
, la estructura completa puede copiarse:
#[derive(Copy, Clone)]
struct Punto {
x: i32,
y: i32,
}
let p1 = Punto { x: 5, y: 10 };
let p2 = p1; // p1 sigue siendo válido
Sin embargo, cuando una estructura contiene tipos como String
que no implementan Copy
, se produce un movimiento de ownership:
let usuario1 = Usuario {
nombre: String::from("Pedro Martín"),
edad: 42,
activo: true,
};
let usuario2 = usuario1; // usuario1 ya no es válido
Referencias en estructuras
Las estructuras pueden contener referencias a datos almacenados en otras ubicaciones, aunque esto requiere el uso de lifetimes para garantizar que las referencias permanezcan válidas:
struct Referencia<'a> {
contenido: &'a str,
}
let texto = "Hola mundo";
let ref_struct = Referencia {
contenido: &texto,
};
Esta capacidad permite crear estructuras que referencian datos sin tomar ownership de ellos, optimizando el uso de memoria en ciertos escenarios.
Métodos asociados
Las estructuras en Rust pueden tener métodos asociados que operan sobre sus instancias, proporcionando una interfaz coherente para manipular los datos encapsulados:
impl Usuario {
fn es_mayor_edad(&self) -> bool {
self.edad >= 18
}
fn cumplir_anos(&mut self) {
self.edad += 1;
}
}
Los métodos de instancia reciben self
como primer parámetro, mientras que las funciones asociadas no lo requieren y se invocan usando la sintaxis ::
:
impl Usuario {
fn nuevo(nombre: String, edad: u32) -> Usuario {
Usuario {
nombre,
edad,
activo: true,
}
}
}
let usuario = Usuario::nuevo(String::from("Laura Sánchez"), 25);
Lecciones de este módulo de Rust
Lecciones de programación del módulo Estructuras de datos del curso de Rust.
Ejercicios de programación en este módulo de Rust
Evalúa tus conocimientos en Estructuras de datos con ejercicios de programación Estructuras de datos de tipo Test, Puzzle, Código y Proyecto con VSCode.