Membres publics vs privés
Fait partie de la section Programmation Orientée Objet du Journey Dart de Coddy — leçon 30 sur 110.
L'encapsulation est l'un des principes fondamentaux de la programmation orientée objet. Il s'agit de contrôler l'accès aux données internes d'une classe, en décidant de ce qui doit être visible par le monde extérieur et de ce qui doit rester caché.
En Dart, les membres de classe (champs et méthodes) sont publics par défaut. Cela signifie que n'importe quel code peut y accéder directement :
class BankAccount {
String owner;
double balance;
BankAccount(this.owner, this.balance);
}
var account = BankAccount('Alice', 1000);
account.balance = -500; // N'importe qui peut modifier cela directement !C'est problématique. Rien n'empêche de définir un solde invalide.
Pour protéger les données internes, Dart utilise des membres privés. Un membre devient privé lorsque son nom commence par un trait de soulignement _ :
class BankAccount {
String owner;
double _balance; // Privé - commence par un trait de soulignement
BankAccount(this.owner, this._balance);
double get balance => _balance; // Accès contrôlé
}Désormais, _balance ne peut plus être accédé directement depuis l'extérieur de la bibliothèque où la classe est définie. Le code externe doit utiliser le getter public à la place. Cela vous permet de contrôler la manière dont les données sont lues et modifiées, garantissant que vos objets restent toujours dans un état valide.
Défi
FacileConstruisons un gestionnaire de mots de passe simple qui démontre la différence entre les membres publics et privés. Vous verrez comment le préfixe underscore protège les données sensibles contre un accès direct depuis l'extérieur de la bibliothèque de la classe.
Vous allez créer deux fichiers pour organiser votre code :
credential.dart: Définissez une classeCredentialqui stocke les informations de connexion pour un site web. La classe doit avoir :- Un
String websitepublic - il n'y a pas de problème à ce que tout le monde voie de quel site il s'agit - Un
String usernamepublic - le nom d'utilisateur peut être visible - Un
String _passwordprivé - le mot de passe réel doit être protégé - Un constructeur qui prend les trois valeurs
- Un getter public
passwordqui retourne le_passwordprivé (accès contrôlé) - Une méthode
getMaskedPassword()qui retourne le mot de passe avec tous les caractères remplacés par des astérisques*(même longueur que le mot de passe réel) - Une méthode
displayCredential()qui affiche les informations d'identification en toute sécurité (en montrant le mot de passe masqué, pas le vrai)
- Un
main.dart: Importez votre classe de justificatifs et démontrez comment l'encapsulation protège le mot de passe :- Créez un justificatif pour le site web
'github.com', l'utilisateur'dev_user', et le mot de passe'secret123' - Créez un autre justificatif pour le site web
'email.com', l'utilisateur'john_doe', et le mot de passe'myP@ss' - Pour chaque justificatif, appelez
displayCredential(), puis affichezActual password length: [length]en utilisant le getter public pour accéder à la longueur du mot de passe
- Créez un justificatif pour le site web
La méthode displayCredential() doit afficher les informations dans ce format :
--- Credential ---
Website: [website]
Username: [username]
Password: [maskedPassword]Résultat attendu :
--- Credential ---
Website: github.com
Username: dev_user
Password: *********
Actual password length: 9
--- Credential ---
Website: email.com
Username: john_doe
Password: ******
Actual password length: 6Aide-mémoire
L'encapsulation contrôle l'accès aux données internes d'une classe en décidant de ce qui doit être visible et de ce qui doit rester caché.
En Dart, les membres d'une classe sont publics par défaut :
class BankAccount {
String owner;
double balance; // Public - can be accessed directly
BankAccount(this.owner, this.balance);
}
var account = BankAccount('Alice', 1000);
account.balance = -500; // Direct modification allowedPour protéger les données internes, utilisez des membres privés en préfixant le nom d'un tiret bas _ :
class BankAccount {
String owner;
double _balance; // Private - starts with underscore
BankAccount(this.owner, this._balance);
double get balance => _balance; // Controlled access via getter
}Les membres privés ne peuvent pas être consultés directement depuis l'extérieur de la bibliothèque où la classe est définie. Utilisez des getters et des méthodes publics pour fournir un accès contrôlé aux données privées, garantissant ainsi que les objets restent dans un état valide.
Essayez vous-même
import 'credential.dart';
void main() {
// TODO: Créer un identifiant pour github.com
// website: 'github.com', username: 'dev_user', password: 'secret123'
// TODO: Appeler displayCredential() sur le premier identifiant
// TODO: Imprimer la longueur réelle du mot de passe en utilisant le getter public
// Format: "Actual password length: [length]"
// TODO: Créer un identifiant pour email.com
// website: 'email.com', username: 'john_doe', password: 'myP@ss'
// TODO: Appeler displayCredential() sur le deuxième identifiant
// TODO: Imprimer la longueur réelle du mot de passe en utilisant le getter public
}
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
1Les bases de la POO
Fichiers externesBibliothèques et importsIntroduction à la POOClasses vs ObjetsLe mot-clé thisMéthodesVariables d'instanceBases des constructeursRécapitulatif - Calculatrice simple4Null Safety
Introduction à la Null SafetyNullable vs Non-NullableLes opérateurs ? et !Le mot-clé late et la Null SafetyLes opérateurs Null-AwareLa Null Safety dans les classesRécapitulatif - Système de profil utilisateur7Classes abstraites et Interfaces
Classes abstraitesMéthodes abstraitesInterfaces en DartInterfaces implicitesImplémentation vs ExtensionInterfaces multiplesRécapitulatif - Calculateur de formes10Collections et Génériques
Aperçu des List, Set et MapCollections Type-SafeClasses génériquesMéthodes génériquesContraintes de généricitéIterable & IteratorRécapitulatif - Stockage générique2Les constructeurs en Dart
Constructeur par défautConstructeurs nommésListes d'initialisationConstructeurs constantsConstructeurs factoryConstructeurs de redirectionRécapitulatif - Shape Builder5Encapsulation
Membres publics vs privésLa convention du préfixe _Visibilité au niveau de la bibliothèqueApprofondissement des Getters & SettersMasquage d'informationsRécapitulatif - Dossiers d'étudiants8Mixins
Introduction aux MixinsCréation de MixinsUtilisation de plusieurs MixinsLe mot-clé on dans les MixinsMixin vs HéritageMixin vs InterfaceRécapitulatif - Système Animal11Méthodes spéciales
Redéfinition de toString()Redéfinition de hashCode & ==Interface ComparableMéthode call()Redéfinition de noSuchMethodRécapitulatif - Collection personnalisée14Patrons de conception Partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FabriquePatron ObservateurPatron Stratégie3Propriétés de classe
Membres d'instance vs statiquesChamps Final & ConstVariables LateMéthodes et champs statiquesGetters et SettersRécapitulatif - Gestionnaire de compte bancaire6Héritage
Bases de l'héritageLe mot-clé superRedéfinition de méthodeL'annotation @overrideLe mot-clé final pour les classesConstructeurs et héritageRécapitulatif - Hiérarchie des employés9Polymorphisme
Bases du polymorphismePolymorphisme via les interfacesVérification de type à l'exécutionLes opérateurs is & asMot-clé covariantRécapitulatif - Processeur de paiement12POO Asynchrone
Futures & async/awaitBases des StreamsStream ControllersConstructeurs asynchronesL'asynchrone dans les méthodes de classeRécapitulatif - Data Fetcher15Patrons de conception Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode ModèlePatron ÉtatPatron CompositePatron Repository