In früheren Versionen von Kotlin wurden sealed Klassen verwendet, um die Typ-Hierarchie einzuschränken, was es Entwicklern ermöglichte, die zulässigen Subtypen deutlich zu steuern, indem sie die Deklaration von Nachkommen auf eine Datei beschränkten. Für einige Aufgaben war dies jedoch unzureichend, insbesondere wenn ähnliche Hierarchien mit Schnittstellen beschrieben werden mussten. Um dieses Problem zu lösen, wurde ab Kotlin 1.5 der sealed Modifikator für Schnittstellen eingeführt.
Normale Schnittstellen erlauben ihre Implementierung überall im Projekt, was häufig die absolute Schließung der Typ-Hierarchie behindert und umfassende Typprüfungen (exhaustive when) verhindert. Dies kann zu Laufzeitfehlern führen und macht es unmöglich, alle Varianten statisch zu überprüfen.
Sealed Interfaces ermöglichen es, die Liste der implementierenden Klassen innerhalb einer Datei einzuschränken, was die Vorhersagbarkeit des Typsystems und die Sicherheit des Pattern Matchings erhöht.
sealed interface NetworkResult class Success(val data: String): NetworkResult class Failure(val error: Throwable): NetworkResult fun handle(result: NetworkResult) = when(result) { is Success -> println("Data: ${result.data}") is Failure -> println("Error: ${result.error}") // Alle Varianten sind berücksichtigt, 'else' ist nicht nötig }
Wesentliche Merkmale:
Kann man ein sealed interface in einer separaten Datei hinzufügen oder außerhalb der ursprünglichen Datei implementieren?
Nein. Alle Typen, die direkt ein sealed interface implementieren, müssen in derselben Datei deklariert werden, andernfalls gibt der Compiler einen Fehler aus.
Darf ein sealed interface Unterinterfaces außerhalb der Deklarationsdatei haben?
Nein. Unterinterfaces müssen ebenfalls in derselben Datei sein. Die gesamte Hierarchie ist innerhalb der Datei geschlossen.
Beeinflussen sealed interfaces die Laufzeitleistung?
Nicht direkt, aber sie ermöglichen die Verwendung sicherer Typprüfungen zur Compile-Zeit, was die Wahrscheinlichkeit von Laufzeitfehlern verringert, den Code vereinfacht und indirekt die Tests beschleunigen kann.
Ein Entwickler erklärt das sealed interface NetworkAction in einer Datei, aber die Implementierungen sind in verschiedenen Klassen und Dateien verstreut. Die Problematik wird spät erkannt: Der Compiler signalisiert einen Verstoß gegen die Regel, die Struktur zu korrigieren ist schwierig, insbesondere in einem großen Projekt.
Vorteile:
Nachteile:
Das sealed interface OrderResult und die Klassen Success/Failure werden innerhalb einer Datei deklariert. Die when-Prüfung ist immer erschöpfend, kein Zweig wird ausgelassen.
Vorteile:
Nachteile: