Menu
Coddy logo textTech

Nascondimento delle informazioni

Fa parte della sezione Programmazione orientata agli oggetti del percorso Dart di Coddy. Lezione 34 di 110.

L'occultamento delle informazioni è il principio alla base dell'incapsulamento: l'idea che una classe dovrebbe nascondere il proprio funzionamento interno ed esporre solo ciò che è necessario. Hai imparato i meccanismi (campi privati, getter, setter), ma il vero obiettivo è progettare classi facili da usare e difficili da usare in modo scorretto.

Considera una classe che gestisce la password di un utente. La logica interna di archiviazione e hashing dovrebbe essere completamente nascosta:

class UserAccount {
  String _username;
  String _passwordHash;
  
  UserAccount(this._username, String password) 
      : _passwordHash = _hashPassword(password);
  
  static String _hashPassword(String password) {
    return 'hashed_$password';  // Simplified example
  }
  
  bool verifyPassword(String password) {
    return _passwordHash == _hashPassword(password);
  }
  
  String get username => _username;
}

Il codice esterno non vede mai l'hash della password né sa come viene memorizzato. Si limita a chiamare verifyPassword(). Questa separazione significa che potresti cambiare completamente l'algoritmo di hashing senza influire su alcun codice che usa questa classe.

L’intuizione chiave è pensare alla tua classe dall’esterno verso l’interno.

Chiediti: "Di cosa ha davvero bisogno chi utilizza questa classe?" Esponi solo questo e mantieni tutto il resto privato. In questo modo si crea un confine chiaro tra ciò che fa la tua classe (la sua interfaccia pubblica) e il modo in cui lo fa (la sua implementazione privata).

challenge icon

Sfida

Facile

Creiamo un sistema di portafoglio sicuro che dimostri in pratica l'occultamento delle informazioni. Creerai un portafoglio digitale che gestisce il saldo e la cronologia delle transazioni di un utente, mantenendo tutti i dettagli interni sensibili completamente nascosti al codice esterno.

Organizzerai il codice in due file:

  • wallet.dart: crea una classe Wallet che gestisca il denaro in modo sicuro. Il portafoglio dovrebbe memorizzare pubblicamente il nome del proprietario, ma tutto il resto dovrebbe essere nascosto dietro un'interfaccia pubblica chiara:
    • Il saldo interno e il registro delle transazioni dovrebbero essere privati: il codice esterno non dovrebbe mai vedere come memorizzi o tieni traccia del denaro
    • Un metodo privato dovrebbe gestire internamente la registrazione delle transazioni (memorizzando voci come "Deposit: $50.0" o "Withdrawal: $30.0")
    • Fornisci un metodo pubblico deposit(double amount) che aggiunga denaro (solo se l'importo è positivo) e registri internamente la transazione
    • Fornisci un metodo pubblico withdraw(double amount) che prelevi denaro solo se i fondi sono sufficienti e l'importo è positivo, registrando internamente la transazione. Restituisci true se l'operazione riesce, altrimenti false
    • Fornisci un getter pubblico balance che restituisca il saldo corrente (accesso in sola lettura)
    • Fornisci un metodo pubblico getTransactionCount() che restituisca il numero di transazioni registrate (senza esporre l'elenco effettivo delle transazioni)
    • Fornisci un metodo pubblico getLastTransaction() che restituisca la stringa della transazione più recente, oppure "No transactions" se non ce ne sono
    • Includi un metodo printSummary() che mostri lo stato del portafoglio
  • main.dart: importa il tuo portafoglio e mostra come l'occultamento delle informazioni crei un'interfaccia chiara e sicura:
    • Crea un portafoglio per il proprietario "Sarah"
    • Deposita 100.0
    • Deposita 50.0
    • Prova a prelevare 200.0 e stampa "Withdrawal of 200.0: [success/failed]" in base al risultato
    • Preleva 30.0 e stampa "Withdrawal of 30.0: [success/failed]"
    • Chiama printSummary()
    • Stampa "Transaction count: [count]"
    • Stampa "Last transaction: [transaction]"

Il metodo printSummary() dovrebbe stampare:

=== Wallet Summary ===
Owner: [ownerName]
Balance: $[balance]

Nota come il codice esterno possa interagire con il portafoglio tramite metodi chiari e mirati senza sapere come viene memorizzato il saldo o come vengono tracciate internamente le transazioni. I dettagli di implementazione sono completamente nascosti: potresti modificare il modo in cui vengono memorizzate le transazioni senza influire sul codice che usa il portafoglio.

Output previsto:

Withdrawal of 200.0: failed
Withdrawal of 30.0: success
=== Wallet Summary ===
Owner: Sarah
Balance: $120.0
Transaction count: 3
Last transaction: Withdrawal: $30.0

Provalo tu

import 'wallet.dart';

void main() {
  // TODO: Crea un monedero para la propietaria "Sarah"
  
  // TODO: Deposita 100.0
  
  // TODO: Deposita 50.0
  
  // TODO: Intenta retirar 200.0 e imprime el resultado
  // Formato: "Withdrawal of 200.0: [success/failed]"
  
  // TODO: Retira 30.0 e imprime el resultado
  // Formato: "Withdrawal of 30.0: [success/failed]"
  
  // TODO: Llama a printSummary()
  
  // TODO: Imprime el número de transacciones
  // Formato: "Transaction count: [count]"
  
  // TODO: Imprime la última transacción
  // Formato: "Last transaction: [transaction]"
}
quiz iconMettiti alla prova

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

Esercitati da solo: Compilatore Dart online