Champs privés
Fait partie de la section Programmation Orientée Objet du Journey Rust de Coddy. Leçon 10 sur 61.
Dans la leçon précédente, vous avez tout rendu public : la structure, ses champs et ses méthodes. Mais une véritable encapsulation consiste à contrôler la manière dont vos données peuvent être consultées. En Rust, vous pouvez rendre une structure publique tout en gardant ses champs privés.
Considère un Wallet qui ne devrait jamais avoir un solde négatif. Si le champ est public, n’importe qui pourrait lui attribuer n’importe quelle valeur :
// wallet.rs
pub struct Wallet {
balance: f64, // Pas de pub = privé !
}
impl Wallet {
pub fn new(initial: f64) -> Wallet {
Wallet { balance: initial }
}
}
Notez que Wallet est public, mais que balance n’a pas le mot-clé pub. Cela signifie que le code situé en dehors du module peut créer un Wallet à l’aide du constructeur, mais ne peut pas lire ou modifier directement le champ balance :
// main.rs
mod wallet;
use wallet::Wallet;
fn main() {
let w = Wallet::new(100.0);
// println!("{}", w.balance); // Erreur ! le champ est privé
// w.balance = -50.0; // Erreur ! impossible d'accéder au champ privé
}
C’est le fondement de l’encapsulation : la struct contrôle ses propres données. Le code externe doit passer par les méthodes que vous fournissez, ce qui signifie que vous pouvez ajouter une validation, une journalisation ou toute autre logique. Les données restent protégées contre les états invalides.
Dans les prochaines leçons, tu apprendras à fournir un accès contrôlé à ces données privées grâce aux méthodes getter et setter.
Défi
FacileConstruisons un système de capteur de température qui démontre l'encapsulation en conservant les données sensibles protégées à l'intérieur d'un module.
Vous allez créer deux fichiers pour organiser votre code :
sensor.rs: définissez une structureTemperatureSensoravec deux champs :location(String) etreading(f64). La structure doit être publique afin de pouvoir être utilisée depuis d'autres fichiers, mais gardez les deux champs privés : le code externe ne doit pas pouvoir accéder directement aux données du capteur ni les modifier. Ajoutez un constructeur publicnewqui prend un nom d'emplacement et une température initiale.main.rs: importez votre module de capteur et créez unTemperatureSensorà l'aide du constructeur. Comme les champs sont privés, vous ne pourrez pas les afficher directement ; affichez plutôt un message de confirmation indiquant que le capteur a été créé avec succès.
Ce défi porte sur le concept fondamental des champs privés : la structure est accessible, mais ses données internes sont protégées. Le code externe ne peut interagir avec le capteur qu'au moyen des méthodes que vous fournissez (dans ce cas, uniquement le constructeur).
Votre sortie doit respecter exactement le format suivant :
Sensor created for: {location}Pour accéder à l'emplacement lors de l'affichage, vous devrez faire en sorte que votre fonction new affiche ce message avant de renvoyer le capteur, puisque le champ lui-même est privé.
Par exemple, si vous créez un capteur avec l'emplacement "Kitchen" et la mesure 22.5, la sortie sera :
Sensor created for: KitchenVous recevrez deux entrées : le nom de l'emplacement et la température initiale.
REQUIRED OUTPUT FORMAT:Essayez vous-même
mod sensor;
use sensor::TemperatureSensor;
fn main() {
// Lire l'entrée
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: Créer un TemperatureSensor en utilisant le constructeur
// La fonction new gérera l'affichage du message de confirmation
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Méthodes et comportement
Introduction aux blocs d'implémentationLe paramètre SelfMéthodes mutablesFonctions associéesBlocs d'implémentation multiplesChaînage de méthodesRécapitulatif - Actions sur le rectangle4Projet : Animal virtuel
Définir l'animalNourrir l'animal7Traits standards
Le trait DebugLe trait DisplayClone et CopyLes traits d'égalitéRécapitulatif - Point affichable10Projet : Système de documents
Le trait DrawComposant texte2Encapsulation et modules
Bases des modulesLe mot-clé publicChamps privésGettersSettersRécapitulatif - Casier sécurisé5Généricité
Structures génériquesMéthodes génériquesPlusieurs types génériquesFonctions génériquesRécapitulatif - Point de coordonnées8Les Traits comme contraintes
Syntaxe des contraintes de traitContraintes multiplesLa clause whereRetourner des types avec des traitsRécapitulatif - Afficheur générique11Design Patterns en Rust
Le pattern NewtypeCompositionLe trait DropFrom et IntoRécapitulatif - Mock de Smart Pointer3Enums avancées
Enums avec donnéesMéthodes sur les EnumsMatching des variantes de donnéesL'Enum Option revisitéeRécapitulatif - Enum Shape6Définition des Traits
Qu'est-ce qu'un Trait ?Implémenter des TraitsImplémentations par défautRedéfinir les comportements par défautTraits avec paramètresRécapitulatif - Lecteur multimédiaEntraînez-vous par vous-même : Compilateur Rust en ligne