Skip to content

Türchen 21

Published: at 07:00 AMSuggest Changes

Private Class Fields – Datenkapselung in Klassen

Mit der Einführung von privaten Klassenfeldern (Private Class Fields) in JavaScript wird die Objektorientierung auf ein neues Level gehoben. Bisher mussten Entwickler Datenkapselung mit Konventionen (etwa Unterstrichen vor Variablennamen) oder Closures erreichen, da alle Eigenschaften von Objekten standardmäßig öffentlich waren. Private Class Fields bieten eine sprachnative Lösung, um Eigenschaften wirklich privat zu halten.

Was sind Private Class Fields?

Private Class Fields sind eine syntaktische Erweiterung in JavaScript, die es ermöglicht, Felder einer Klasse als wirklich privat zu deklarieren. Diese Felder sind nicht von außen sichtbar und können nur innerhalb der Klassenmethoden oder -zugriffe eingesehen oder verändert werden.

Merkmale von Private Class Fields:

Syntax-Beispiel

class Person {
  #name; // privates Feld

  constructor(name) {
    this.#name = name;
  }

  greet() {
    console.log(`Hallo, mein Name ist ${this.#name}.`);
  }
}

const p = new Person('Anna');
p.greet(); // "Hallo, mein Name ist Anna."
console.log(p.#name); // SyntaxError: Private field '#name' must be declared in an enclosing class

In diesem Beispiel ist #name ein privates Feld von Person. Das heißt, wir können außerhalb der Klasse nicht direkt auf p.#name zugreifen.

Vorteile von Private Class Fields

  1. Echte Datenkapselung:
    Anders als bei den bisherigen Konventionen (wie etwa Unterstriche vor Eigenschaftsnamen), kann wirklich niemand unabsichtlich oder wissentlich auf private Felder zugreifen. Dies steigert die Robustheit des Codes und garantiert die Integrität der Daten.

  2. Wartbarkeit:
    Da man sicher sein kann, dass private Felder nur innerhalb der Klasse verändert werden, kann der interne Zustand einer Klasse freier angepasst werden, ohne für externe Zugriffe rückwärtskompatibel sein zu müssen.

  3. Klare Intentionalität:
    Der Code kommuniziert deutlich, welche Daten im Inneren der Klasse verbleiben und nicht für den direkten Zugriff von außen bestimmt sind.

Praktische Beispiele

  1. Interne Zustandsverwaltung

    class BankAccount {
      #balance = 0;
    
      constructor(initialDeposit) {
        this.#balance = initialDeposit;
      }
    
      deposit(amount) {
        if (amount <= 0) throw new Error('Invalid deposit amount');
        this.#balance += amount;
      }
    
      withdraw(amount) {
        if (amount > this.#balance) throw new Error('Not enough funds');
        this.#balance -= amount;
      }
    
      getBalance() {
        // Externen Zugriff nur über eine Methode erlauben
        return this.#balance;
      }
    }
    
    const account = new BankAccount(100);
    account.deposit(50);
    console.log(account.getBalance()); // 150
    // Direkter Zugriff: console.log(account.#balance); // SyntaxError!
    

    In diesem Beispiel wird die Kontostand-Variable #balance nur innerhalb der Klasse verwaltet. Von außen kann der Nutzer lediglich über Methoden einzahlen, abheben oder den Kontostand erfragen. Direkter Zugriff ist ausgeschlossen.

  2. Implementierung von “Private” Helper-Methoden

    Private Felder können auch Funktionen sein, wenn sie als Arrow Function in der Klasse deklariert werden. So kann man interne Hilfsfunktionen verstecken, die nicht Teil der öffentlichen API der Klasse sind.

    class PasswordChecker {
      #secretHash; 
      #hashFunction = (pwd) => {
        // Simpler Hash-Mechanismus für Demo-Zwecke
        return pwd.split('').reverse().join('');
      };
    
      constructor(password) {
        this.#secretHash = this.#hashFunction(password);
      }
    
      validate(password) {
        return this.#hashFunction(password) === this.#secretHash;
      }
    }
    
    const checker = new PasswordChecker('topsecret');
    console.log(checker.validate('wrongpass')); // false
    console.log(checker.validate('topsecret')); // true
    
    // Von außen kein Zugriff auf checker.#secretHash oder checker.#hashFunction
    

    Hier wird die interne Hash-Funktion #hashFunction privat gehalten, sodass nur PasswordChecker selbst weiß, wie Passwörter gehasht werden.

  3. Interne Caches oder Lazy Evaluation

    In komplexen Anwendungen kann man mit privaten Feldern interne Caches anlegen, ohne dass externe Nutzer diese manipulieren oder einsehen können. Zum Beispiel bei der Berechnung teurer Werte kann man den Wert einmal berechnen und in einem privaten Feld speichern.

    class Computation {
      #cache = null;
    
      computeExpensiveValue() {
        if (this.#cache !== null) return this.#cache;
        // Simulierte teure Berechnung:
        let result = 0;
        for (let i = 0; i < 1_000_000; i++) {
          result += Math.sqrt(i);
        }
        this.#cache = result;
        return result;
      }
    }
    
    const comp = new Computation();
    console.log(comp.computeExpensiveValue()); // teure Berechnung beim ersten Aufruf
    console.log(comp.computeExpensiveValue()); // sofortiger Zugriff aus dem Cache beim zweiten Aufruf
    // Von außen kein direkter Zugriff auf #cache möglich
    

    Nutzer der Computation-Klasse haben keinerlei Möglichkeit, #cache direkt auszulesen oder zu manipulieren. Die interne Architektur bleibt gekapselt.

Einschränkungen und Hinweise

Fazit

Private Class Fields bringen echte Datenkapselung in JavaScript-Klassen. Damit können interne Zustände geschützt, konsistente APIs definiert und robustere, leichter wartbare Codebasen erstellt werden. Von sicherer Datenverwaltung bei Bankkonten über versteckte Hilfsfunktionen zur Passwortvalidierung bis hin zu unsichtbaren Caches für teure Berechnungen – private Felder eröffnen neue Möglichkeiten, sauberen objektorientierten Code zu schreiben.

Experimentiere mit Private Class Fields in deinem nächsten Projekt und entdecke neue Möglichkeiten, sauberen objektorientierten Code zu schreiben!


Previous Post
Türchen 22
Next Post
Türchen 20