Menu
Coddy logo textTech

Campos Privados

Parte da seção Object Oriented Programming do Journey de Rust da Coddy — lição 10 de 61.

Na lição anterior, você tornou tudo público—a struct, seus campos e seus métodos. Mas o verdadeiro encapsulamento significa controlar como seus dados podem ser acessados. Em Rust, você pode tornar uma struct pública enquanto mantém seus campos privados.

Considere uma Wallet que nunca deve ter um saldo negativo. Se o campo for público, qualquer pessoa poderia defini-lo para qualquer valor:

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

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

Observe que Wallet é pública, mas balance não possui a palavra-chave pub. Isso significa que o código fora do módulo pode criar uma Wallet usando o construtor, mas não pode ler ou modificar diretamente o campo balance:

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

fn main() {
    let w = Wallet::new(100.0);
    // println!("{}", w.balance);  // Erro! o campo é privado
    // w.balance = -50.0;          // Erro! não é possível acessar o campo privado
}

Este é o fundamento do encapsulamento — a struct controla seus próprios dados. O código externo deve passar pelos métodos que você fornece, o que significa que você pode adicionar validação, log ou qualquer outra lógica. Os dados permanecem protegidos contra estados inválidos.

Nas próximas lições, você aprenderá como fornecer acesso controlado a esses dados privados através de métodos getter e setter.

challenge icon

Desafio

Fácil

Vamos construir um sistema de sensor de temperatura que demonstra o encapsulamento, mantendo dados sensíveis protegidos dentro de um módulo.

Você criará dois arquivos para organizar seu código:

  • sensor.rs: Defina uma struct TemperatureSensor com dois campos: location (String) e reading (f64). A struct deve ser pública para que possa ser usada em outros arquivos, mas mantenha ambos os campos privados — o código externo não deve ser capaz de acessar ou modificar diretamente os dados do sensor. Adicione um construtor público new que receba um nome de localização e uma leitura de temperatura inicial.
  • main.rs: Importe seu módulo de sensor e crie um TemperatureSensor usando o construtor. Como os campos são privados, você não poderá imprimi-los diretamente — em vez disso, imprima uma mensagem de confirmação mostrando que o sensor foi criado com sucesso.

Este desafio foca no conceito central de campos privados: a struct é acessível, mas seus dados internos estão protegidos. O código externo só pode interagir com o sensor através dos métodos que você fornece (neste caso, apenas o construtor).

Sua saída deve seguir este formato exato:

Sensor created for: {location}

Para acessar a localização para impressão, você precisará fazer com que sua função new imprima esta mensagem antes de retornar o sensor, já que o campo em si é privado.

Por exemplo, se você criar um sensor com a localização "Kitchen" e leitura 22.5, a saída seria:

Sensor created for: Kitchen

Você receberá duas entradas: o nome da localização e a leitura inicial da temperatura.

Folha de consulta

Em Rust, você pode tornar uma struct pública enquanto mantém seus campos privados para alcançar o encapsulamento. Isso impede que o código externo acesse ou modifique diretamente os dados internos.

Para tornar um campo privado, basta omitir a palavra-chave pub:

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

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

Neste exemplo, Wallet é pública (pode ser usada fora do módulo), mas balance é privado (não pode ser acessado diretamente de fora).

O código externo pode criar instâncias usando construtores públicos, mas não pode ler ou modificar campos privados:

mod wallet;
use wallet::Wallet;

fn main() {
    let w = Wallet::new(100.0);
    // println!("{}", w.balance);  // Erro! o campo é privado
    // w.balance = -50.0;          // Erro! não é possível acessar o campo privado
}

Esse encapsulamento garante que a struct controle seus próprios dados, e o código externo deve usar os métodos que você fornece para interagir com ela.

Experimente você mesmo

mod sensor;

use sensor::TemperatureSensor;

fn main() {
    // Ler 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: Criar um TemperatureSensor usando o construtor
    // A função new lidará com a impressão da mensagem de confirmação
    
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Object Oriented Programming