Middle
Jaka jest różnica między klasami sealed a klasami abstrakcyjnymi w Kotlin?
sobes.tech AI
Odpowiedź od AI
Główna różnica między klasami sealed a abstrakcyjnymi polega na tym, że klasy sealed ograniczają hierarchię dziedziczenia do jednego pliku lub modułu (dla Kotlin 1.5+). Następcy klasy sealed muszą być zadeklarowani w tym samym pliku co sama klasa sealed, co zapewnia wyczerpującą kontrolę podczas korzystania z wyrażeń when.
Różnice:
- Dziedziczenie:
- Klasy abstrakcyjne mogą być dziedziczone w dowolnym miejscu projektu.
- Klasy sealed mogą być dziedziczone tylko w tym samym pliku (przed Kotlin 1.5) lub w tym samym module (z Kotlin 1.5+).
- Użycie z
when:- Używając
whenz typem sealed, kompilator może sprawdzić, czy wszystkie możliwe podtypy zostały uwzględnione, co czyniwhenwyczerpującym i eliminuje konieczność jawnego podawania gałęzielse, jeśli wszystkie podtypy są obsłużone. - Z klasami abstrakcyjnymi kompilator nie może zagwarantować wyczerpywalności, dlatego często konieczne jest dodanie
else.
- Używając
- Tworzenie instancji:
- Ani klasy abstrakcyjne, ani sealed nie mogą być bezpośrednio instancjonowane.
- Członkowie:
- Zarówno klasy abstrakcyjne, jak i sealed mogą mieć członków abstrakcyjnych i nieabstrakcyjnych.
Przykład klasy sealed:
sealed class Result<out T> {
data class Success<out T>(val data: T) : Result<T>()
data class Error(val message: String) : Result<Nothing>()
}
fun processResult(result: Result<Int>) {
when (result) {
is Result.Success -> {
// Obsługa sukcesu
println("Sukces: ${result.data}")
}
is Result.Error -> {
// Obsługa błędu
println("Błąd: ${result.message}")
}
// Nie jest potrzebny else, jeśli obsłużono wszystkie podtypy
}
}
Przykład klasy abstrakcyjnej:
abstract class Shape {
abstract fun area(): Double
}
class Circle(val radius: Double) : Shape() {
override fun area(): Double = Math.PI * radius * radius
}
class Rectangle(val width: Double, val height: Double) : Shape() {
override fun area(): Double = width * height
}
fun calculateArea(shape: Shape): Double {
return shape.area()
}
Kiedy używać:
- Klasy sealed: Doskonałe do reprezentowania ograniczonego zestawu stanów lub typów, gdy potrzebujesz wyczerpującej kontroli w wyrażeniach
when. Często używane do modelowania wyników operacji (sukces/błąd), stanów UI, zdarzeń. - Klasy abstrakcyjne: Odpowiednie do definiowania ogólnej funkcjonalności i kontraktów dla grupy powiązanych klas, które mogą być dziedziczone w dowolnym miejscu w projekcie.
Podsumowując, klasy sealed zapewniają bardziej rygorystyczną kontrolę nad hierarchią dziedziczenia i poprawiają bezpieczeństwo oraz czytelność kodu podczas obsługi ograniczonego zestawu podtypów.