Visibilité au niveau de la bibliothèque
Fait partie de la section Programmation Orientée Objet du Journey Dart de Coddy — leçon 32 sur 110.
En Dart, la confidentialité est appliquée au niveau de la bibliothèque, et non au niveau de la classe. C'est une distinction clé par rapport à des langages comme Java ou C++. Une bibliothèque en Dart est généralement un fichier unique, ou plusieurs fichiers connectés avec des directives part.
Les membres privés (ceux commençant par _) sont accessibles n'importe où dans la même bibliothèque, même depuis d'autres classes :
// Les deux classes sont dans le même fichier (même bibliothèque)
class Engine {
int _horsepower = 200; // Privé à cette bibliothèque
}
class Car {
void showPower(Engine engine) {
print(engine._horsepower); // Accessible ! Même bibliothèque
}
}Cependant, lorsque vous importez une classe depuis un fichier différent, ses membres privés deviennent véritablement cachés :
// fichier : engine.dart
class Engine {
int _horsepower = 200;
int get power => _horsepower;
}
// fichier : main.dart
import 'engine.dart';
void main() {
var engine = Engine();
// print(engine._horsepower); // Erreur ! Non accessible
print(engine.power); // Fonctionne - utilise le getter public
}Cette confidentialité au niveau de la bibliothèque signifie que les classes d'un même fichier peuvent collaborer étroitement tout en masquant les détails d'implémentation au code externe. C'est un choix de conception délibéré qui encourage l'organisation de classes liées ensemble dans la même bibliothèque.
Défi
FacileConstruisons un système de collaboration d'équipe qui démontre le fonctionnement de la confidentialité au niveau de la bibliothèque en Dart. Vous verrez comment des classes situées dans le même fichier peuvent accéder aux membres privés les unes des autres, alors que le code situé dans des fichiers séparés ne le peut pas.
Vous organiserez votre code en deux fichiers :
team.dart: Ce fichier contiendra deux classes qui travaillent en étroite collaboration dans la même bibliothèque :- Une classe
Memberavec unString namepublic et unint _performanceScoreprivé initialisé à50. Incluez un constructeur qui prend le nom, et un getter publicperformanceScorequi retourne le score privé. - Une classe
TeamLeaddans le même fichier qui peut accéder directement au champ privé deMember(car ils sont dans la même bibliothèque). Cette classe doit avoir unString namepublic, un constructeur qui prend le nom, et une méthodeevaluateMember(Member member)qui accède directement àmember._performanceScore, lui ajoute10, et affiche[leadName] boosted [memberName]'s score to [newScore].
- Une classe
main.dart: Importez votre fichier d'équipe et démontrez la différence d'accès :- Créez un
Membernommé'Alice' - Créez un
TeamLeadnommé'Bob' - Affichez
Initial score: [score]en utilisant le getter public sur Alice - Faites en sorte que Bob évalue Alice en utilisant
evaluateMember - Affichez
Updated score: [score]en utilisant le getter public - Affichez
Direct access from main: Not allowed(cela nous rappelle quemain.dartne peut pas accéder directement à_performanceScorepuisqu'il se trouve dans une bibliothèque différente)
- Créez un
L'idée clé ici est que TeamLead peut directement lire et modifier le _performanceScore privé de Member car les deux classes résident dans le même fichier (même bibliothèque). Cependant, le code dans main.dart doit utiliser le getter public car il se trouve dans une bibliothèque différente.
Sortie attendue :
Initial score: 50
Bob boosted Alice's score to 60
Updated score: 60
Direct access from main: Not allowedAide-mémoire
En Dart, la confidentialité est appliquée au niveau de la bibliothèque, et non au niveau de la classe. Une bibliothèque est généralement un fichier unique, ou plusieurs fichiers connectés avec des directives part.
Les membres privés commencent par un trait de soulignement (_) et sont accessibles n'importe où dans la même bibliothèque, même depuis d'autres classes :
// Les deux classes sont dans le même fichier (même bibliothèque)
class Engine {
int _horsepower = 200; // Privé à cette bibliothèque
}
class Car {
void showPower(Engine engine) {
print(engine._horsepower); // Accessible ! Même bibliothèque
}
}Lorsque vous importez une classe depuis un fichier différent, ses membres privés deviennent masqués :
// fichier : engine.dart
class Engine {
int _horsepower = 200;
int get power => _horsepower;
}
// fichier : main.dart
import 'engine.dart';
void main() {
var engine = Engine();
// print(engine._horsepower); // Erreur ! Non accessible
print(engine.power); // Fonctionne - utilise un getter public
}Cette conception encourage l'organisation de classes liées ensemble dans la même bibliothèque, leur permettant de collaborer étroitement tout en masquant les détails d'implémentation du code externe.
Essayez vous-même
import 'team.dart';
void main() {
// TODO: Créer un Member nommé 'Alice'
// TODO: Créer un TeamLead nommé 'Bob'
// TODO: Afficher "Initial score: [score]" en utilisant le getter public sur Alice
// TODO: Faire en sorte que Bob évalue Alice en utilisant evaluateMember
// TODO: Afficher "Updated score: [score]" en utilisant le getter public
// TODO: Afficher "Direct access from main: Not allowed"
// Note: Nous ne pouvons pas accéder à alice._performanceScore ici car
// main.dart est dans une bibliothèque différente de team.dart
}
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