ProgrammierungWeiterführendesPrivate Eigenschaften

Private Eigenschaften mit get und set

💡

Dauer: 25 Minuten

  • Private Eigenschaften in Klassen verhindern den Zugriff von „außen“
  • get und set ermöglichen kontrollierten Zugriff

Ziel: Kapselung bzw. data hiding für den Zustand für Objekte einer Klasse

Manchmal sollen bestimmte Eigenschaften eines Objekts nicht direkt von außen sichtbar bzw. veränderbar sein. Dadurch soll z.B. das Setzen ungültiger Zustände von Objekten verhindert werden:

class Person {
  age = 0; 
  // age (das Alter einer Person) kann von 
  // anderem Code willkürlich geändert werden	
}
	
let john = new Person();
	
// Alter wird auf eine unzulässige Zahl gesetzt
// dies wollen wir vielleicht verhindern!!!
john.age = -1424;

Idealerweise wird hier das direkte Ändern der Werte von Objekteigenschaften verhindert.

Mit dem Zusatz # vor ihrem Namen kann eine Instanzvariable oder Methode für den Zugriff von außen verborgen werden. Dadurch steht die Instanzvariable bzw. Methode nur dem Code innerhalb der Klasse zur Verfügung.

Durch den Zusatz # vor dem Namen gekennzeichnete Variablen bzw. Methoden werden als „privat“ bezeichnet, denn von außen dürfen diese nicht verwendet werden. Siehe dazu folgendes Beispiel:

class Person {	
  #age; // #age ist privat, wird durch Konstruktor gesetzt
	
  constructor(age) {	
    this.#age = age;	
  }	
}
 
let jane = new Person(23);
		
// Auf #age darf außerhalb der Klasse gar nicht zugegriffen werden	
jane.#age = -1424; // ---> SyntaxError
jane.#age = 24;  // ---> SyntaxError

Oben ist zu sehen, wie age durch #age als private Eigenschaft markiert wird. Beim Versuch auf diese Eigenschaft „von außen“ zuzugreifen entsteht ein Syntax-Fehler.

Der Vorgang des „Verbergens“ von Eigenschaften wird in der objektorientierten Programmierung „Kapselung“ oder auch information/data hiding genannt.

In anderen Sprachen gibt es noch weitere Konzepte wie z.B. protected, d.h. weitere Arten der Zugriffsmodifikatoren.

Mit dem Konstruktor wird #age nun bei der Objekterzeugung initialisiert.

Aber wie können wir nun das Alter von Personen abfragen und ändern?

getter- und setter-Methoden

Durch sogenannte getter- und setter-Methoden können private Eigenschaften von Objekten für den lesenden (getter) und den schreibenden (setter) Zugriff „von außerhalb“ bei Verwendung eines Objekts zugänglich gemacht werden.

In JavaScript stehen hierzu die Schlüsselwörter get für getter- und set für setter-Methoden bereit. Für eine private Eigenschaft #prop werden getter/setter durch Voranstellen von get und set vor dem Methodennamen definiert. Die Methode muss dabei den Namen der privaten Eigenschaft ohne den Zusatz # haben:

class ExampleClass { 
  #prop;
 
  // getter für #prop
  get prop() { 
    return this.#prop;
  }
 
  // setter für #prop
  set prop(prop) { 
    this.#prop = prop;
  }
}

Der getter liefert also den Wert der Eigenschaft als Rückgabewert und der setter hat einen Parameter für die Zuweisung eines neuen Wertes. Neben der Rückgabe im getter und der Zuweisung im setter sind weitere Anweisungen in den Methoden möglich.

In unserem Beispiel mit Person und #age könnten wir passende getter und setter folgendermaßen umsetzen, sodass der Parameter im setter auf Gültigkeit überprüft wird:

class Person {
  #age; // #age privat, wird durch Konstruktor und getter gesetzt
	
  constructor(age=0) {
    this.#age = age;
  }
	
  // getter-Methode für age
  // #age wird zurückgeliefert
  get age() { 
    return this.#age; 
  }
	
  // setter-Methode für age mit Parameter
  // nur sinnvolle Werte werden zugelassen
  set age(age) {	
    if(age<0 || age>120) {
      throw new Error('invalid age!');
      // Fehler --> Alter wird nicht geändert
    }
 
    // private Instanzvariable ändern	
    this.#age = age; 
  }	
}
‼️

⟶ Zu beachten ist das Leerzeichen jeweils nach get und set!

Wenn getter- bzw. setter-Methoden mit get bzw. set vorhanden sind, dann kann wieder direkt auf die Eigenschaften mit der gewohnten Punktnotation (object.prop) zugegriffen werden (ohne #):

const alice = new Person(23);
console.log(alice.age); // 23
 
try {    
  alice.age = 32;
  console.log(alice.age); // 32
  alice.age = -1234; // erzeugt Laufzeitfehler!
} catch(error) {
  // Error: invalid age!
  console.error(error);
} finally {
  console.log("Alter am Ende: " + alice.age); // 32
}

Private Methoden

Auch Methoden können durch das Voranstellen von # am Methodennamen als privat markiert werden. Diese dürfen dann nur innerhalb der Klasse mit this aufgerufen werden:

class Example {
  #secretMethod() {
    return "pssst!";
  }
 
  revealSecret() {
    return this.#secretMethod();
  }
}
 
const tmp = new Example();
tmp.secretMethod(); // --> TypeError
tmp.#secretMethod(); // --> SyntaxError
tmp.revealSecret(); // --> "pssst!"

Vertiefendes Material