programowanieProgramista Android/Kotlin

Czym są interfejsy sealed w Kotlinie, jak i po co ich używać?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź.

Interfejs sealed to specjalny typ interfejsu w Kotlinie, który pozwala ograniczyć liczbę jego implementacji w ramach jednego modułu. Po raz pierwszy klasy sealed pojawiły się w Kotlinie wcześniej, a interfejsy sealed zostały dodane od wersji Kotlin 1.5 jako ewolucja w celu lepszej kontroli nad typami, które biorą udział w hierarchiach stanów lub obsłudze zdarzeń.

Historia pytania

Wcześniej programiści używali klas sealed do ograniczenia dziedziczenia i tworzenia bezpiecznych hierarchii. Jednak dla elastyczności i wsparcia struktur, w których dziedziczenie z wielu typów jest przydatne, potrzebne były interfejsy sealed.

Problem

Bez interfejsów sealed nie można elastycznie zarządzać zestawem podklas interfejsu. To uniemożliwia na przykład wyczerpującą kontrolę przy użyciu when podczas obsługi stanów, jeśli wszystko jest oparte na interfejsach, a nie tylko na klasach abstrakcyjnych/konkretnych.

Rozwiązanie

Użycie interfejsu sealed pozwala:

  • Opisać stały zestaw implementacji.
  • Gwarantować, że wszystkie implementacje są znane kompilatorowi.
  • Bezpiecznie używać when bez gałęzi else — kompilator wskazuje na nietrafione przypadki.

Przykład kodu:

sealed interface Event class Click : Event class Scroll : Event fun handle(event: Event) = when(event) { is Click -> println("Wydarzenie kliknięcia") is Scroll -> println("Wydarzenie przewijania") }

Kluczowe cechy:

  • Ograniczenie i kontrola zestawu dozwolonych implementacji.
  • Możliwość dziedziczenia z wielu interfejsów sealed jednocześnie.
  • Bezpieczeństwo przy dopasowywaniu wzorców (when).

Podchwytliwe pytania.

Czy interfejsy sealed mogą mieć implementacje poza plikiem ich deklaracji?

Nie, implementacje interfejsu sealed muszą znajdować się w tym samym module. Gwarantuje to pełną wyczerpującość i pozwala kompilatorowi kontrolować ich liczbę.

Jak interfejsy sealed współdziałają z klasami i obiektami?

Interfejs sealed może być implementowany zarówno przez klasy zwykłe, jak i obiekty, a także przez obiekty danych (Kotlin 1.9+). Taki interfejs może występować w wielu dziedziczeniach, czego nie można zrobić z klasą sealed.

sealed interface Operation object Add: Operation object Subtract: Operation

Czy interfejsy sealed mogą być zagnieżdżone?

Tak, można deklarować interfejs sealed zarówno wewnątrz innej klasy sealed, jak i ponad innymi interfejsami. Ważne jest, aby wszystkie implementacje znajdowały się w jednym module.

Typowe błędy i antywzorce

  • Określenie implementacji interfejsu sealed w różnych modułach prowadzi do błędów kompilacji.
  • Próba użycia interfejsu sealed na podstawie domniemania, że jest on jak klasa sealed, mimo że interfejs sealed może być dziedziczony przez inne interfejsy.

Przykład z życia

Negatywny przypadek

W aplikacji stany UI opisano po prostu jako interfejsy bez modyfikatora sealed. Zapomniano o jednej implementacji, analiza statyczna tego nie wychwyciła; błąd ujawnił się dopiero w produkcji.

Zalety:

  • Znany wzorzec interfejsów Java.

Wady:

  • Brak gwarancji wyczerpującości w when.
  • Wrażliwość na pojawienie się implementacji "z zewnątrz".

Pozytywny przypadek

Użycie interfejsu sealed do modelu zdarzeń ekranu. Wszystkie implementacje znajdują się w jednym pliku modułu, kompilator informuje o niezamkniętych gałęziach, jeśli w when pominięto przypadek.

Zalety:

  • Pełne bezpieczeństwo typów.
  • Wygoda w utrzymaniu i rozszerzaniu.

Wady:

  • Użycie tylko w ramach jednego modułu.