Menu
Coddy logo textTech

Campos privados

Parte de la sección Object Oriented Programming del Journey de Rust de Coddy — lección 10 de 61.

En la lección anterior, hiciste que todo fuera público —el struct, sus campos y sus métodos. Pero la verdadera encapsulación significa controlar cómo se puede acceder a tus datos. En Rust, puedes hacer que un struct sea público mientras mantienes sus campos privados.

Considera una Wallet que nunca debería tener un saldo negativo. Si el campo es público, cualquiera podría establecerlo en cualquier valor:

// wallet.rs
pub struct Wallet {
    balance: f64,  // ¡Sin pub = privado!
}

impl Wallet {
    pub fn new(initial: f64) -> Wallet {
        Wallet { balance: initial }
    }
}

Observa que Wallet es pública, pero balance no tiene la palabra clave pub. Esto significa que el código fuera del módulo puede crear una Wallet usando el constructor, pero no puede leer ni modificar directamente el campo balance:

// main.rs
mod wallet;
use wallet::Wallet;

fn main() {
    let w = Wallet::new(100.0);
    // println!("{}", w.balance);  // ¡Error! el campo es privado
    // w.balance = -50.0;          // ¡Error! no se puede acceder al campo privado
}

Este es el fundamento del encapsulamiento: el struct controla sus propios datos. El código externo debe pasar por los métodos que proporciones, lo que significa que puedes añadir validación, registro o cualquier otra lógica. Los datos permanecen protegidos de estados inválidos.

En las próximas lecciones, aprenderás cómo proporcionar acceso controlado a estos datos privados a través de métodos getter y setter.

challenge icon

Desafío

Fácil

Construyamos un sistema de sensor de temperatura que demuestre el encapsulamiento manteniendo los datos sensibles protegidos dentro de un módulo.

Crearás dos archivos para organizar tu código:

  • sensor.rs: Define una estructura TemperatureSensor con dos campos: location (String) y reading (f64). La estructura debe ser pública para que pueda usarse desde otros archivos, pero mantén ambos campos privados; el código externo no debería poder acceder o modificar directamente los datos del sensor. Agrega un constructor público new que reciba un nombre de ubicación y una lectura de temperatura inicial.
  • main.rs: Incorpora tu módulo de sensor y crea un TemperatureSensor usando el constructor. Dado que los campos son privados, no podrás imprimirlos directamente; en su lugar, imprime un mensaje de confirmación que muestre que el sensor se creó correctamente.

Este desafío se centra en el concepto central de los campos privados: la estructura es accesible, pero sus datos internos están protegidos. El código externo solo puede interactuar con el sensor a través de los métodos que proporciones (en este caso, solo el constructor).

Tu salida debe seguir este formato exacto:

Sensor created for: {location}

Para acceder a la ubicación para imprimirla, necesitarás que tu función new imprima este mensaje antes de devolver el sensor, ya que el campo en sí es privado.

Por ejemplo, si creas un sensor con la ubicación "Kitchen" y la lectura 22.5, la salida sería:

Sensor created for: Kitchen

Recibirás dos entradas: el nombre de la ubicación y la lectura de temperatura inicial.

Hoja de referencia

En Rust, puedes hacer que una estructura sea pública mientras mantienes sus campos privados para lograr el encapsulamiento. Esto evita que el código externo acceda o modifique directamente los datos internos.

Para hacer que un campo sea privado, simplemente omite la palabra clave pub:

pub struct Wallet {
    balance: f64,  // Sin pub = campo privado
}

impl Wallet {
    pub fn new(initial: f64) -> Wallet {
        Wallet { balance: initial }
    }
}

En este ejemplo, Wallet es pública (se puede usar fuera del módulo), pero balance es privado (no se puede acceder directamente desde fuera).

El código externo puede crear instancias utilizando constructores públicos, pero no puede leer ni modificar campos privados:

mod wallet;
use wallet::Wallet;

fn main() {
    let w = Wallet::new(100.0);
    // println!("{}", w.balance);  // ¡Error! el campo es privado
    // w.balance = -50.0;          // ¡Error! no se puede acceder al campo privado
}

Este encapsulamiento garantiza que la estructura controle sus propios datos, y el código externo debe utilizar los métodos que proporciones para interactuar con ella.

Pruébalo tú mismo

mod sensor;

use sensor::TemperatureSensor;

fn main() {
    // Leer entrada
    let mut location = String::new();
    std::io::stdin().read_line(&mut location).expect("Failed to read line");
    let location = location.trim().to_string();
    
    let mut reading_str = String::new();
    std::io::stdin().read_line(&mut reading_str).expect("Failed to read line");
    let reading: f64 = reading_str.trim().parse().expect("Failed to parse reading");
    
    // TODO: Crear un TemperatureSensor usando el constructor
    // La función new se encargará de imprimir el mensaje de confirmación
    
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Object Oriented Programming