Menu
Coddy logo textTech

Information Hiding

Teil des Abschnitts Objektorientierte Programmierung der Dart-Journey von Coddy — Lektion 34 von 110.

Information Hiding ist das Prinzip hinter der Kapselung – die Idee, dass eine Klasse ihre internen Abläufe verbergen und nur das Notwendige offenlegen sollte. Sie haben die Mechanismen kennengelernt (private fields, getters, setters), aber das eigentliche Ziel ist der Entwurf von Klassen, die einfach zu verwenden und schwer falsch zu bedienen sind.

Betrachten Sie eine Klasse, die das Passwort eines Benutzers verwaltet. Die interne Speicherung und die Hashing-Logik sollten vollständig verborgen sein:

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

Externer Code sieht niemals den Passwort-Hash oder weiß, wie er gespeichert wird. Sie rufen einfach verifyPassword() auf. Diese Trennung bedeutet, dass Sie den Hashing-Algorithmus vollständig ändern könnten, ohne den Code zu beeinflussen, der diese Klasse verwendet.

Die entscheidende Erkenntnis besteht darin, Ihre Klasse von außen nach innen zu betrachten.

Fragen Sie sich: „Was benötigt jemand, der diese Klasse verwendet, tatsächlich?“ Geben Sie nur das frei und halten Sie alles andere privat. Dies schafft eine klare Grenze zwischen dem, was Ihre Klasse tut (ihre öffentliche Schnittstelle), und wie sie es tut (ihre private Implementierung).

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein sicheres Wallet-System bauen, das Information Hiding in Aktion demonstriert. Sie werden ein digitales Wallet erstellen, das das Guthaben und den Transaktionsverlauf eines Benutzers verwaltet und dabei alle sensiblen internen Details vor externem Code vollständig verborgen hält.

Sie werden Ihren Code in zwei Dateien organisieren:

  • wallet.dart: Erstellen Sie eine Wallet-Klasse, die Geld sicher verwaltet. Das Wallet sollte den Namen des Besitzers öffentlich speichern, aber alles andere sollte hinter einer sauberen öffentlichen Schnittstelle verborgen sein:
    • Das interne Guthaben und das Transaktionsprotokoll sollten privat sein – externer Code sollte niemals sehen, wie Sie Geld speichern oder verfolgen.
    • Eine private Methode sollte das interne Aufzeichnen von Transaktionen übernehmen (Speichern von Einträgen wie "Deposit: $50.0" oder "Withdrawal: $30.0").
    • Stellen Sie eine öffentliche Methode deposit(double amount) bereit, die Geld hinzufügt (nur wenn der Betrag positiv ist) und die Transaktion intern aufzeichnet.
    • Stellen Sie eine öffentliche Methode withdraw(double amount) bereit, die Geld nur dann abhebt, wenn ausreichend Guthaben vorhanden ist und der Betrag positiv ist, und die Transaktion intern aufzeichnet. Geben Sie true zurück, wenn dies erfolgreich war, andernfalls false.
    • Stellen Sie einen öffentlichen Getter balance bereit, der das aktuelle Guthaben zurückgibt (Nur-Lese-Zugriff).
    • Stellen Sie eine öffentliche Methode getTransactionCount() bereit, die zurückgibt, wie viele Transaktionen aufgezeichnet wurden (ohne die tatsächliche Transaktionsliste offenzulegen).
    • Stellen Sie eine öffentliche Methode getLastTransaction() bereit, die den neuesten Transaktions-String zurückgibt, oder "No transactions", falls keine vorhanden sind.
    • Fügen Sie eine Methode printSummary() hinzu, die den Status des Wallets anzeigt.
  • main.dart: Importieren Sie Ihr Wallet und demonstrieren Sie, wie Information Hiding eine saubere, sichere Schnittstelle schafft:
    • Erstellen Sie ein Wallet für den Besitzer "Sarah".
    • Zahlen Sie 100.0 ein.
    • Zahlen Sie 50.0 ein.
    • Versuchen Sie, 200.0 abzuheben, und geben Sie "Withdrawal of 200.0: [success/failed]" basierend auf dem Ergebnis aus.
    • Heben Sie 30.0 ab und geben Sie "Withdrawal of 30.0: [success/failed]" aus.
    • Rufen Sie printSummary() auf.
    • Geben Sie "Transaction count: [count]" aus.
    • Geben Sie "Last transaction: [transaction]" aus.

Die Methode printSummary() sollte Folgendes ausgeben:

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

Beachten Sie, wie externer Code über klare, zweckgerichtete Methoden mit dem Wallet interagieren kann, ohne jemals zu wissen, wie das Guthaben gespeichert wird oder wie Transaktionen intern verfolgt werden. Die Implementierungsdetails sind vollständig verborgen – Sie könnten die Art und Weise, wie Transaktionen gespeichert werden, ändern, ohne den Code zu beeinflussen, der das Wallet verwendet.

Erwartete Ausgabe:

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

Spickzettel

Information Hiding ist das Prinzip hinter der Kapselung – das Verbergen der internen Funktionsweise einer Klasse und das Offenlegen nur dessen, was notwendig ist.

Entwerfen Sie Klassen von außen nach innen: Legen Sie nur das offen, was Benutzer benötigen, und halten Sie alles andere privat. Dies schafft eine klare Grenze zwischen der öffentlichen Schnittstelle (was die Klasse tut) und der privaten Implementierung (wie sie es tut).

Beispiel für Information Hiding mit einem Passwort-Manager:

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

Externer Code sieht niemals den Passwort-Hash oder den Speichermechanismus – er verwendet nur verifyPassword(). Dies ermöglicht es, die interne Implementierung zu ändern, ohne den externen Code zu beeinflussen.

Probier es selbst

import 'wallet.dart';

void main() {
  // TODO: Erstelle eine Wallet für die Besitzerin "Sarah"
  
  // TODO: Zahle 100.0 ein
  
  // TODO: Zahle 50.0 ein
  
  // TODO: Versuche 200.0 abzuheben und gib das Ergebnis aus
  // Format: "Withdrawal of 200.0: [success/failed]"
  
  // TODO: Hebe 30.0 ab und gib das Ergebnis aus
  // Format: "Withdrawal of 30.0: [success/failed]"
  
  // TODO: Rufe printSummary() auf
  
  // TODO: Gib die Anzahl der Transaktionen aus
  // Format: "Transaction count: [count]"
  
  // TODO: Gib die letzte Transaktion aus
  // Format: "Last transaction: [transaction]"
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung