Sealed Class — isang espesyal na uri ng klase sa Kotlin na naglilimita sa hierarchy ng pamamana sa isang nakapirming hanay ng mga subtype. Lahat ng tagapagmana ay idineklara sa parehong file at kilala ng compiler, na nagbibigay-daan sa paggamit ng isang masusing when-block na walang mandatoryong else branch. Ayon sa Kotlin Docs, 2026, ang mga sealed na klase ay pangunahing mekanismo para kumatawan sa limitadong hierarchy tulad ng mga estado, uri ng error, at mga kaganapan sa UI.
Pangunahing Punto
Sealed Class (sealed na klase) — ito ay isang klase sa Kotlin na may markang sealed modifier. Tinutukoy nito ang isang limitadong hierarchy ng uri: lahat ng posibleng tagapagmana ay nakalista sa parehong file, at alam ng compiler ang bawat isa sa kanila. Ito ay nagpapakilala sa sealed class mula sa isang ordinaryong bukas na klase, na ang mga tagapagmana ay maaaring ideklara kahit saan.
Ang pangunahing layunin ng sealed class ay type-safe na representasyon ng isang may hangganang hanay ng mga variant. Bawat tagapagmana ay maaaring magkaroon ng sariling istruktura ng data, na ginagawang mas flexible ang sealed class kaysa sa enum. Sa runtime, ang sealed class ay isang ordinaryong abstract class, ang compiler ay nagpapataw lamang ng mga paghihigpit sa yugto ng compilation.
Ang sealed class ay lalong kapaki-pakinabang sa arkitektura ng Android na mga aplikasyon: mga estado ng UI, resulta ng mga kahilingan sa network, mga kaganapan sa nabigasyon na parang Intent, at siyempre, mga hierarchy ng error — karaniwang mga senaryo ng aplikasyon.
Sa compilation, ang sealed class ay na-optimize sa isang transition table para sa when expression, na ginagawang mas episyente kaysa sa if-else chain. Sa kombinasyon sa data class, ang bawat tagapagmana ay maaaring maglaman hindi lamang ng estado, kundi pati na rin ng mga pamamaraan, na nagpapahintulot sa pagbuo ng mga self-documenting domain model na walang boilerplate code.
Ang sealed class ay epektibo rin para kumatawan sa finite state machine sa mga mobile application. Bawat estado — isang hiwalay na tagapagmana na may natatanging parameter, at ang mga transition sa pagitan ng estado ay kinokontrol sa pamamagitan ng when expression. Ginagarantiyahan ng compiler na ang lahat ng posibleng estado ay naproseso, na nag-aalis ng mga runtime error kapag nagbago ang estado ng UI o lohika ng negosyo.
Ang mga nagsisimulang developer ng Kotlin ay madalas na nalilito ang sealed class sa enum, dahil parehong nililimitahan ang hanay ng mga halaga. Ngunit may pangunahing pagkakaiba sa pagitan nila: enum — isang hanay ng mga constant ng parehong uri, sealed class — isang hierarchy ng iba't ibang uri.
Enum ay optimal kapag ang lahat ng variant ay mga constant na walang karagdagang istruktura. Halimbawa, mga araw ng linggo, katayuan ng order, o mga uri ng aksyon na walang parameter. Bawat halaga ng enum ay isang singleton na may nakapirming pangalan.
Sealed class ay kailangan kapag bawat variant ay may sariling data. Halimbawa, ang error sa network ay naglalaman ng code ng tugon, error sa parsing — mga detalye, at error sa awtorisasyon — isang mensahe. Bawat tagapagmana ng sealed class ay isang hiwalay na uri na may natatanging field.
// Enum — lahat ng variant ng isang uri
enum class Status { LOADING, SUCCESS, ERROR }
// Sealed class — bawat variant na may sariling data
sealed class UiState<out T> {
object Loading : UiState<Nothing>()
data class Success<T>(val data: T) : UiState<T>()
data class Error(val message: String) : UiState<Nothing>()
}
Mula sa Kotlin 1.5, may posibilidad na magdeklara ng sealed interface. Pinapalawak nito ang konsepto ng sealed sa mga interface: ang sealed interface ay mayroon ding nakapirming hanay ng mga implementasyon, ngunit sumusuporta sa maramihang pamamana.
Sealed interface ay maginhawa kapag ang mga tagapagmana ay kailangang magpatupad ng maraming kontrata nang sabay-sabay. Halimbawa, ang isang kaganapan sa UI ay maaaring sabay na pindutin at masubaybayan. Sa sealed class, kailangang pumili ng isang base class, sa sealed interface, ang tagapagmana ay nagpapatupad ng pareho.
Sealed class ay isang klase, kaya ang bawat tagapagmana ay maaari lamang magkaroon ng isang magulang. Nilulutas ng sealed interface ang problemang ito, ngunit hindi maaaring maglaman ng estado. Ang pagpili sa pagitan nila ay depende sa gawain: kailangan ang karaniwang lohika na may mga field — sealed class, kailangan ang flexibility ng mga kontrata — sealed interface.
sealed interface ScreenEvent {
data class Refresh(val force: Boolean) : ScreenEvent
data class Navigate(val route: String) : ScreenEvent
data class ShowError(val toast: String) : ScreenEvent
}
sealed interface AnalyticsEvent {
val name: String
val params: Map<String, Any>
}
// Ang tagapagmana ay nagpapatupad ng parehong interface
data class LoginClicked(
override val name: String = "login_click",
override val params: Map<String, Any> = emptyMap()
) : ScreenEvent, AnalyticsEvent
Isa sa mga pangunahing aplikasyon ng sealed class sa pag-develop ng mobile — type-safe na hierarchy ng error. Sa halip na magtapon ng mga exception ng iba't ibang uri o gumamit ng pangkalahatang Exception, kinokolekta ng sealed class ang lahat ng posibleng error ng domain sa isang uri.
Lumikha ng sealed class na DomainError at ilista ang lahat ng uri ng pagkabigo bilang mga tagapagmana. Bawat tagapagmana ay naglalaman lamang ng mga data na may kahulugan para sa uri ng error na iyon. Ginagarantiyahan ng compiler na sa paghawak ng error, hindi mo malilimutan ang anumang variant.
Isaalang-alang ang isang aplikasyon na may awtorisasyon, kung saan posible ang iba't ibang senaryo ng pagkabigo: maling password, pag-block ng account, problema sa server. Pinagsasama sila ng sealed class sa isang uri na may masusing paghawak.
sealed class AuthError {
data class InvalidCredentials(
val attempts: Int
) : AuthError()
data class AccountBlocked(
val until: Long
) : AuthError()
data class NetworkFailure(
val cause: Throwable
) : AuthError()
object ServerError : AuthError()
}
fun handleError(error: AuthError): String = when (error) {
is AuthError.InvalidCredentials ->
"Natitirang pagsubok: ${3 - error.attempts}"
is AuthError.AccountBlocked ->
"Na-block ang access hanggang ${Date(error.until)}"
is AuthError.NetworkFailure ->
"Suriin ang koneksyon: ${error.cause.localizedMessage}"
AuthError.ServerError ->
"Pansamantalang hindi available ang server"
}
Sealed class ay naging karaniwang kasangkapan sa arkitektura ng mga aplikasyon ng Android. Tingnan natin ang tatlong pangunahing pattern kung saan ang sealed class ay kailangang-kailangan sa pag-develop ng mobile.
Hiwalay, nararapat banggitin ang aplikasyon ng sealed class sa Clean Architecture. Bawat layer (data, domain, presentation) ay gumagamit ng sealed class para sa sarili nitong mga uri ng error, at ang mga mapper ay nagko-convert ng isang sealed class sa isa pa. Halimbawa, ang DataError mula sa data layer ay na-map sa DomainError para sa lohika ng negosyo, pagkatapos ay sa UiState para sa presentation layer. Ito ay nagpapanatili ng type-safety sa lahat ng antas ng aplikasyon at ginagarantiyahan na walang error ang mananatiling hindi naproseso.
Pagsubok sa sealed class ay nangangailangan ng espesyal na diskarte, dahil bawat tagapagmana ay isang hiwalay na uri na may sariling estado. Inirerekomenda na magsulat ng mga parameterized na pagsubok na dumadaan sa lahat ng tagapagmana ng sealed class. Ito ay ginagarantiyahan na ang when expression ay sumasaklaw sa lahat ng variant, kabilang ang mga bago na idinagdag sa pagpapalawak ng hierarchy.
Para sa mga pagsubok sa UI, ang sealed class bilang UiState ay nagpapahintulot sa pagsusuri ng pagpapakita ng bawat estado: Loading ay nagpapakita ng spinner, Content — data, Error — mensahe ng error. Dahil ang sealed class ay may hangganan, ang test coverage ng lahat ng estado ay nagbibigay ng buong katiyakan sa kawastuhan ng lohika ng UI.
Sa kabila ng pagiging simple ng konsepto, ang mga developer ay regular na nagkakamali sa pagdidisenyo ng sealed class hierarchy. Tingnan natin ang mga pangunahing problema at paraan upang maiwasan ang mga ito.
Mga Madalas Itanong
Oo, ang sealed class ay maaaring maglaman ng abstract na pamamaraan, at bawat tagapagmana ay obligadong ipatupad ang mga ito. Ito ay maginhawa kapag ang lahat ng variant ay dapat magbigay ng isang karaniwang interface, ngunit may iba't ibang lohika ng pagpapatupad.
Sa Java 17+ ay lumitaw ang mga sealed na klase at interface na may sealed modifier. Ang Android ay kasalukuyang bahagyang sumusuporta sa Java 17, ngunit sa mga proyekto ng Kotlin, ang sealed class ay available mula sa Kotlin 1.0 nang walang mga paghihigpit.
Oo, ang isang sealed class ay maaaring maging tagapagmana ng isa pa. Ang hierarchy ng sealed class ay nananatiling may hangganan: alam ng compiler ang lahat ng tagapagmana sa bawat antas. Nagbibigay-daan ito sa pagbuo ng detalyadong pag-uuri ng mga error.
Ang sealed class ay hindi lumilikha ng overhead sa runtime. Ino-optimize ng compiler ang when expression na may sealed class sa mga transition table (tableswitch), na mas mabilis kaysa sa if-else chain. Ang pagganap ay kapareho ng enum.
Bawat tagapagmana ng sealed class ay sinusuri nang hiwalay. Dahil ang sealed class ay may hangganan, maaaring magsulat ng isang parameterized na pagsubok na dumadaan sa lahat ng variant. Nagbibigay ito ng kumpletong coverage ng mga branch ng when block.
Buod
Gagawa kami ng mobile application na turnkey
Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.
Basahin din