Public get private set in Kotlin: Fallstricke und Lösungen

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Public get, private set in Kotlin: Wie man Fehler vermeidet (und was man tut, wenn man sie bereits gemacht hat)

\n\n

Hallo Kollege! Wenn du jemals "Kotlin public get private set var" gegoogelt hast, bist du nicht allein. Diese Suchanfrage ist ein echter Hit auf Stack Overflow, und Tausende von Entwicklern (mich eingeschlossen, damals) haben sich den Kopf über die Tastatur geschlagen, um zu verstehen, warum ihr Code nicht funktioniert.

\n\n

Es scheint doch einfach zu sein? Ich möchte, dass die Eigenschaft für alle zugänglich ist (public get), aber nur die Klasse selbst sie ändern kann (private set). In Java war das Routine: ein privates Feld deklarieren, einen Getter und Setter schreiben und den Setter privat machen. In Kotlin sollte alles einfacher sein, aber...

\n\n

Spoiler: Die Syntax existiert, aber sie funktioniert nicht immer so, wie du es erwartest. In diesem Artikel analysieren wir die häufigsten Fehler, die selbst erfahrene Entwickler machen, und zeigen, wie man sie vermeidet. Los geht's!

\n\n

Anatomie einer Eigenschaft: var, val, get und set

\n\n

Zunächst eine kurze Einführung. In Kotlin sind Eigenschaften (properties) nicht nur einfache Felder. Sie sind vollwertige Elemente, die Getter und Setter enthalten können. Hier ist die grundlegende Struktur:

\n\n
var eigenschaftsname: Typ = standardwert\n    get() = field\n    set(value) { field = value }
\n\n

Wenn du var verwendest, generiert Kotlin automatisch einen Getter und einen Setter. Du kannst ihr Verhalten jedoch überschreiben. Und du kannst auch ihre Sichtbarkeit ändern (Sichtbarkeitsmodifikatoren: public, private, internal, protected).

\n\n

Und hier wird es interessant. Um den Getter öffentlich und den Setter privat zu machen, musst du schreiben:

\n\n
var name: String = "standard"\n    private set
\n\n

Das war's? Fast. Aber es gibt Nuancen, die diesen Mechanismus stören.

\n\n

Fehler Nr. 1: Den Konstruktor vergessen

\n\n

Das häufigste Problem ist der Versuch, public get private set var im Konstruktor einer Klasse zu deklarieren. Zum Beispiel:

\n\n
// ❌ Fehler: So geht das nicht\nclass User(public get private set var name: String)
\n\n

Kotlin gibt einen Kompilierungsfehler aus. Warum? Weil die Parameter eines Konstruktors keine Eigenschaften sind. Es sind nur Parameter. Wenn du möchtest, dass eine Eigenschaft eine geänderte Setter-Sichtbarkeit hat, muss sie im Rumpf der Klasse deklariert werden.

\n\n

So ist es richtig:

\n\n
class User(name: String) {\n    var name: String = name\n        private set\n}
\n\n

Oder, wenn du eine data class verwendest, musst du einen Umweg gehen:

\n\n
data class User(private val _name: String) {\n    var name: String = _name\n        private set\n}
\n\n

Ja, data class erlaubt es nicht, die Setter-Sichtbarkeit für Eigenschaften aus dem primären Konstruktor direkt zu ändern. Du musst ein Backing Field verwenden.

\n\n

Fehler Nr. 2: Verwirrung mit dem Backing Field

\n\n

Ein Backing Field ist ein verstecktes Feld, das Kotlin automatisch für eine Eigenschaft generiert, wenn du field im Getter oder Setter verwendest. Wenn du jedoch den Getter oder Setter überschreibst, ohne auf field zuzugreifen, wird kein Backing Field erstellt.

\n\n

Beispiel für ein Problem:

\n\n
var counter: Int = 0\n    private set\n    get() = field * 2 // ❌ Fehler: field ist nicht definiert
\n\n

Nein, das ist kein Kompilierungsfehler. Aber wenn du schreibst:

\n\n
var counter: Int = 0\n    private set\n    get() = 42 // alles ok, aber field wird nicht verwendet
\n\n

In diesem Fall wird kein Backing Field erstellt. Und wenn du versuchst, im Setter auf field zuzugreifen, erhältst du einen Fehler. Die gute Nachricht: Wenn du private set verwendest, wird das Backing Field fast immer automatisch erstellt, da der Standard-Setter field verwendet. Aber wenn du den Setter ohne field überschreibst, sei auf Überraschungen gefasst.

\n\n

Tipp: Verwende immer explizit field im Getter und Setter, wenn du mit dem Backing Field arbeiten möchtest. Und denk daran: Wenn eine Eigenschaft kein Backing Field hat, ...

Blogs

Buchempfehlungen