Visibilità a livello di libreria
Fa parte della sezione Programmazione orientata agli oggetti del percorso Dart di Coddy. Lezione 32 di 110.
In Dart, la privacy viene applicata a livello di libreria, non a livello di classe. Questa è una distinzione fondamentale rispetto a linguaggi come Java o C++. Una libreria in Dart è in genere un singolo file o più file collegati tramite direttive part.
I membri privati (quelli che iniziano con _) sono accessibili ovunque all'interno della stessa libreria, anche da altre classi:
// Entrambe le classi nello stesso file (stessa libreria)
class Engine {
int _horsepower = 200; // Privato per questa libreria
}
class Car {
void showPower(Engine engine) {
print(engine._horsepower); // Accessibile! Stessa libreria
}
}Tuttavia, quando importi una classe da un file diverso, i suoi membri privati diventano davvero nascosti:
// file: engine.dart
class Engine {
int _horsepower = 200;
int get power => _horsepower;
}
// file: main.dart
import 'engine.dart';
void main() {
var engine = Engine();
// print(engine._horsepower); // Errore! Non accessibile
print(engine.power); // Funziona - usa un getter pubblico
}Questa privacy a livello di libreria consente alle classi nello stesso file di collaborare strettamente, nascondendo al contempo i dettagli di implementazione al codice esterno. È una scelta progettuale intenzionale che incoraggia a organizzare le classi correlate nella stessa libreria.
Sfida
FacileCreiamo un sistema di collaborazione tra team che dimostri come funziona la privacy a livello di libreria in Dart. Vedrai come le classi nello stesso file possono accedere ai membri privati delle altre, mentre il codice in file separati non può farlo.
Organizzerai il codice in due file:
team.dart: questo file conterrà due classi che collaborano strettamente nella stessa libreria:- Una classe
Membercon unString namepubblico e unint _performanceScoreprivato inizializzato a50. Includi un costruttore che accetta il nome e un getter pubblicoperformanceScoreche restituisce il punteggio privato. - Una classe
TeamLeadnello stesso file, che può accedere direttamente al campo privato diMember(perché si trovano nella stessa libreria). Questa classe dovrebbe avere unString namepubblico, un costruttore che accetta il nome e un metodoevaluateMember(Member member)che accede direttamente amember._performanceScore, vi aggiunge10e stampa[leadName] boosted [memberName]'s score to [newScore].
- Una classe
main.dart: importa il file del team e mostra la differenza nell'accesso:- Crea un
Memberchiamato'Alice' - Crea un
TeamLeadchiamato'Bob' - Stampa
Initial score: [score]usando il getter pubblico di Alice - Fai valutare Alice a Bob usando
evaluateMember - Stampa
Updated score: [score]usando il getter pubblico - Stampa
Direct access from main: Not allowed(questo ci ricorda chemain.dartnon può accedere direttamente a_performanceScoreperché si trova in una libreria diversa)
- Crea un
L'intuizione chiave è che TeamLead può leggere e modificare direttamente il campo privato _performanceScore di Member perché entrambe le classi si trovano nello stesso file (la stessa libreria). Tuttavia, il codice in main.dart deve usare il getter pubblico perché si trova in una libreria diversa.
Output previsto:
Initial score: 50
Bob boosted Alice's score to 60
Updated score: 60
Direct access from main: Not allowedProvalo tu
import 'team.dart';
void main() {
// TODO: Crea un Member chiamato 'Alice'
// TODO: Crea un TeamLead chiamato 'Bob'
// TODO: Stampa "Initial score: [score]" usando il getter pubblico di Alice
// TODO: Fai valutare Alice a Bob usando evaluateMember
// TODO: Stampa "Updated score: [score]" usando il getter pubblico
// TODO: Stampa "Direct access from main: Not allowed"
// Nota: Non possiamo accedere a alice._performanceScore qui perché
// main.dart si trova in una libreria diversa da team.dart
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Fondamenti della programmazione orientata agli oggetti
File esterniLibrerie e importazioniIntroduzione alla programmazione orientata agli oggettiClassi e oggettiLa parola chiave thisMetodiVariabili di istanzaFondamenti dei costruttoriRiepilogo - Calcolatrice semplice4Sicurezza dei valori null
Introduzione alla sicurezza dei valori nullNullable e non nullableGli operatori ? e !La keyword late e la sicurezza dei valori nullOperatori null-awareSicurezza dei valori null nelle classiRiepilogo - Sistema di profili utente7Classi astratte e interfacce
Classi astratteMetodi astrattiInterfacce in DartInterfacce impliciteImplementare vs estendereInterfacce multipleRiepilogo - Calcolatore di forme10Collezioni e generici
Panoramica di List, Set e MapCollezioni sicure rispetto ai tipiClassi genericheMetodi genericiVincoli sui genericiIterable e IteratorRiepilogo - Archiviazione generica13Concetti avanzati di OOP
Composizione vs ereditarietàMetodi di estensioneClassi chiamabiliClassi sealed (Dart 3)Record (Dart 3)Pattern e matching (3.0)Enum con metodi16Progetto: Gestione della biblioteca
Panoramica del progettoClassi Libro e Utente2I costruttori in Dart
Costruttore predefinitoCostruttori con nomeListe di inizializzazioneCostruttori costantiCostruttori factoryCostruttori di reindirizzamentoRiepilogo - Crea forme5Incapsulamento
Membri pubblici e privatiConvenzione del prefisso _Visibilità a livello di libreriaApprofondimento su getter e setterNascondimento delle informazioniRiepilogo - Registri degli studenti8Mixin
Introduzione ai MixinCreare MixinUsare più MixinParola chiave on nei MixinMixin vs ereditarietàMixin vs interfacciaRiepilogo - Sistema animale11Metodi speciali
Sovrascrittura di toString()Sovrascrittura di hashCode e ==Interfaccia ComparableMetodo call()Sovrascrittura di noSuchMethodRiepilogo - Collezione personalizzata14Modelli di progettazione Parte 1
Introduzione ai modelli di progettazioneSingletonFactoryObserverStrategy3Proprietà delle classi
Membri di istanza e staticiCampi final e constVariabili lateMetodi e campi staticiGetter e setterRiepilogo - Gestore di conti bancari6Ereditarietà
Ereditarietà di baseLa parola chiave superOverride dei metodiL’annotazione @overrideLa parola chiave final per le classiCostruttori ed ereditarietàRiepilogo - Gerarchia dei dipendenti9Polimorfismo
Fondamenti di polimorfismoPolimorfismo tramite interfacceControllo del tipo a runtimeGli operatori is e asParola chiave covariantRiepilogo - Elaboratore di pagamenti12OOP asincrona
Future e async/awaitNozioni di base sugli streamController degli streamCostruttori asincroniAsync nei metodi di classeRiepilogo - Recupero dei dati15Pattern di progettazione Parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern CompositePattern RepositoryEsercitati da solo: Compilatore Dart online