Campos Privados
Parte da seção Programação Orientada a Objetos 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 poderá defini-lo como 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úblico, mas balance não tem a palavra-chave pub. Isso significa que o código fora do módulo pode criar um Wallet usando o construtor, mas não pode ler ou modificar diretamente o campo de saldo:
// 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 precisa passar pelos métodos que você fornece, o que significa que você pode adicionar validação, registro em log ou qualquer outra lógica. Os dados permanecem protegidos contra estados inválidos.
Nas próximas lições, você aprenderá a fornecer acesso controlado a esses dados privados por meio de métodos getter e setter.
Desafio
FácilVamos criar um sistema de sensor de temperatura que demonstra encapsulamento mantendo dados sensíveis protegidos dentro de um módulo.
Você criará dois arquivos para organizar seu código:
sensor.rs: Defina uma structTemperatureSensorcom dois campos:location(String) ereading(f64). A struct deve ser pública para que possa ser usada a partir de outros arquivos, mas mantenha ambos os campos privados: o código externo não deve conseguir acessar ou modificar diretamente os dados do sensor. Adicione um construtor públiconewque receba um nome de localização e uma leitura inicial de temperatura.main.rs: Inclua seu módulo do sensor e crie umTemperatureSensorusando 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 se concentra no conceito fundamental de campos privados: a struct é acessível, mas seus dados internos são protegidos. O código externo só pode interagir com o sensor por meio dos métodos que você fornecer (neste caso, apenas o construtor).
Sua saída deve seguir este formato exato:
Sensor created for: {location}Para acessar a localização e imprimi-la, você precisará fazer com que sua função new imprima esta mensagem antes de retornar o sensor, já que o próprio campo é privado.
Por exemplo, se você criar um sensor com a localização "Kitchen" e a leitura 22.5, a saída será:
Sensor created for: KitchenVocê receberá duas entradas: o nome da localização e a leitura inicial de temperatura.
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: Crie um TemperatureSensor usando o construtor
// A função new irá lidar com a impressão da mensagem de confirmação
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Métodos e Comportamento
Introdução a Blocos de ImplementaçãoO Parâmetro SelfMétodos MutáveisFunções AssociadasMúltiplos Blocos de ImplementaçãoEncadeamento de MétodosRecapitulação - Ações de Retângulo4Projeto: Pet Virtual
Definindo o PetAlimentando o Pet7Traits Padrão
A Trait DebugA Trait DisplayClone e CopyTraits de IgualdadeRecapitulação - Ponto Imprimível10Projeto: Sistema de Documentos
A Trait DrawComponente de Texto2Encapsulamento e Módulos
Fundamentos de MódulosA Palavra-chave PublicCampos PrivadosGettersSettersRecapitulação - Cofre Seguro5Genéricos
Structs GenéricasMétodos GenéricosMúltiplos Tipos GenéricosFunções GenéricasRecapitulação - Ponto de Coordenada8Traits como Restrições
Sintaxe de Restrições de TraitRestrições MúltiplasA Cláusula WhereRetornando Tipos com TraitsRecapitulação - Impressora Genérica11Padrões de Projeto em Rust
Padrão NewtypeComposiçãoA Trait DropFrom e IntoRecapitulação - Mock de Smart Pointer3Enums Avançados
Enums com DadosMétodos em EnumsCorrespondência de Variantes de DadosO Enum Option RevisitadoRecapitulação - Enum Shape6Definição de Traits
O que é uma Trait?Implementando TraitsImplementações PadrãoSobrescrevendo PadrõesTraits com ParâmetrosRecapitulação - Media PlayerPratique por conta própria: Compilador de Rust online