Specyfika Kotlina w programowaniu mobilnym: co to jest, jakie konstrukcje i jak działa

Autor: IT Sectr Opublikowano: 2026-06-29 Czas czytania: 11 min

Kotlin jest głównym językiem do programowania Androida. Według Google Android Docs (2025), ponad 95% nowych projektów na Androida używa Kotlina. Zrozumienie specyfiki Kotlina — data class, sealed class, korutyny i scope functions — jest obowiązkowym wymogiem dla programisty Androida.

Najważniejsze

  • data class — automatyczne generowanie equals/hashCode/toString/copy/componentN. Dla modeli danych. sealed class — ograniczona hierarchia typów ze sprawdzaniem when.
  • Scope functions: let, run, with, apply, also. Różnią się kontekstem (it vs this) i wartością zwracaną.
  • Korutyny: launch (fire-and-forget), async (z wynikiem), runBlocking (most), withContext (zmiana Dispatcher).
  • lifecycleScope i viewModelScope — korutyny Lifecycle-aware bez ręcznego anulowania.
  • reified — zachowanie typu w funkcjach inline. lateinit/lazy — opóźniona inicjalizacja.

Klasy (data class, sealed class, object, companion object)

Kotlin rozszerza koncepcje klas z Javy. data class, sealed class, object i companion object — konstrukcje, które nie istnieją w Javie lub są zaimplementowane inaczej.

data class vs sealed class

data class — klasa automatycznie generująca equals(), hashCode(), toString(), copy() i componentN(). Idealna dla modeli danych (DTO, Entity). Wymagania: co najmniej jeden parametr w konstruktorze głównym, val/var, nie może być open/sealed/inner. sealed class — klasa z ograniczoną hierarchią podklas. Wszystkie podklasy są znane w czasie kompilacji i zadeklarowane w tym samym pliku. Wyrażenie when z sealed class nie wymaga gałęzi else. sealed interface (Kotlin 1.9+) — to samo co sealed class, ale pozwala na wielodziedziczenie. object — singleton, deklarowany słowem kluczowym object (nie class). Bezpieczna wątkowo leniwa inicjalizacja. companion object — statyczne elementy klasy. Ma nazwę (domyślnie Companion). Może implementować interfejsy i mieć extension functions.

Typ Opis Zastosowanie
data classAutomatyczne generowanie equals, hashCode, toString, copyModele danych, DTO, Entity
sealed classOgraniczona hierarchia, sprawdzanie whenStany, Wynik, UI State
sealed interfacesealed class + wielodziedziczenieZdarzenia, Akcje (Kotlin 1.9+)
objectSingleton (deklaratywny)Factory, Utility, Stałe
companion objectStatyczne elementy klasyFactory Method, statyczne stałe
enum classWyliczenie ze stałymiStany ze stałym zestawem

data class — dla 90% modeli. sealed class — dla UI State i Wyniku. object — dla singletonów. IT Sectr zaleca sealed class dla wszystkich stanów ekranu (Loading, Success, Error).

Sealed class w praktyce

Sealed class — potężne narzędzie do modelowania stanów. Przykład: UiState<T> z podklasami Loading, Success(data: T), Error(message: String). Wyrażenie when gwarantuje obsługę wszystkich stanów. Sealed interface — dla zdarzeń i akcji, gdzie potrzebna jest wielokrotna implementacja. Value class (Kotlin 1.5+) — opakowanie dla pojedynczej wartości bez narzutu. Używane do bezpiecznych typowo identyfikatorów: @JvmInline value class UserId(val id: String).

Funkcje (extension, inline, higher-order, scope functions)

Extension Function — dodanie metody do istniejącej klasy bez dziedziczenia. fun String.isEmail(): Boolean. Extension Property — to samo dla właściwości (bez backing field). Inline Function — wstawienie ciała funkcji w miejscu wywołania — bez narzutu wywołania. Używane dla funkcji higher-order z lambdami. Higher-Order Function — funkcja przyjmująca lub zwracająca inną funkcję. Scope Functions — pięć funkcji do pracy z kontekstem obiektu: let, run, with, apply, also.

Scope Functions

let — kontekst it, zwraca wynik lambdy. Używane do wywołań null-safe (?.let {}). apply — kontekst this, zwraca kontekst. Do konfiguracji obiektu. run — kontekst this, zwraca wynik lambdy. Do obliczeń z kontekstem. also — kontekst it, zwraca kontekst. Do efektów ubocznych (logowanie). with — nie jest extension, kontekst this, zwraca wynik lambdy. Do grupy operacji na obiekcie. Lambda — funkcja anonimowa. Destructuring Declaration — rozpakowanie data class na zmienne: val (name, age) = person.

Inline + reified

Inline function z reified — jedyny sposób zachowania typu generycznego w JVM. Używane do: bezpiecznych typowo builderów (Gson.fromJson<T>()), sprawdzania typów (is T), pobierania klasy (T::class). Crossinline i Noinline — modyfikatory parametrów lambda w funkcjach inline. crossinline — zabrania non-local return, noinline — zabrania inline'owania konkretnej lambdy. IT Sectr zaleca inline + reified tylko podczas pracy z typami; dla zwykłych funkcji higher-order, inline może zwiększyć rozmiar bytecodu.

Korutyny (Coroutine Builder, Dispatchers, Scope)

Korutyny — lekkie wątki do programowania asynchronicznego. Nie blokują wątku — zawieszają się (suspend). suspend function — funkcja, którą można zawiesić bez blokowania wątku. Może być wywołana tylko z korutyny lub innej suspend function.

CoroutineScope

CoroutineScope — zakres korutyn. Zawiera CoroutineContext (Job + Dispatcher). lifecycleScope — dla Activity/Fragment (Lifecycle-aware). viewModelScope — dla ViewModel (automatyczne anulowanie przy onCleared()). GlobalScope — globalny zakres (nie używać w produkcji — wycieki pamięci). Dispatchers: Dispatchers.Main (UI), Dispatchers.IO (sieć/dysk), Dispatchers.Default (CPU-intensive), Dispatchers.Unconfined (niezalecane). launch — uruchomienie korutyny: Job. async — uruchomienie z wynikiem: Deferred<T>. runBlocking — blokujący most. withContext — zmiana Dispatcher wewnątrz suspend function.

kotlin
// Przykład korutyn: ładowanie danych w ViewModel
class MainViewModel : ViewModel() {
    private val _state = MutableStateFlow<UiState>(UiState.Loading)
    val state: StateFlow<UiState> = _state.asStateFlow()

    fun loadData() {
        viewModelScope.launch {
            _state.value = UiState.Loading
            try {
                val data = withContext(Dispatchers.IO) {
                    repository.fetchData()
                }
                _state.value = UiState.Success(data)
            } catch (e: Exception) {
                _state.value = UiState.Error(e.message)
            }
        }
    }
}

// Równoległe żądania z async
suspend fun loadCombinedData(): CombinedData = coroutineScope {
    val users = async(Dispatchers.IO) { api.getUsers() }
    val posts = async(Dispatchers.IO) { api.getPosts() }
    CombinedData(users.await(), posts.await())
}

viewModelScope.launch — standardowe uruchomienie korutyny w ViewModel. withContext(Dispatchers.IO) — przełączenie na wątek IO dla żądania sieciowego. Dispatchers określają, na której puli wątków wykonuje się korutyna. IT Sectr zaleca viewModelScope dla ViewModel i lifecycleScope dla Activity/Fragment.

Zaawansowane funkcje (reified, destructuring, lateinit/lazy)

reified — modyfikator typu w funkcjach inline. Pozwala użyć typu: T::class, is T, as T. Bez reified, generyki w JVM są wymazywane (type erasure). inline fun + reified — potężna kombinacja dla bezpiecznych typowo API. Destructuring Declaration — val (x, y) = point. Działa dla data class i typów z componentN(). typealias — alias typu: typealias Callback = (String) -> Unit. lateinit — opóźniona inicjalizacja var (dla dependency injection). Niebezpieczny wątkowo. lazy — leniwa inicjalizacja val (domyślnie bezpieczna wątkowo). lazy(LazyThreadSafetyMode.NONE) — bez synchronizacji. Extension function i Extension property — dodawanie funkcjonalności bez dziedziczenia. Kotlin to język, w którym extension functions rozwiązują 90% zadań narzędziowych.

Właściwości Delegowane

Delegated Properties — delegowanie getter/setter do innego obiektu. Standardowe delegaty: lazy, observable, vetoable, map. Niestandardowy delegat przez operatory getValue/setValue. by — słowo kluczowe delegacji: val name by lazy { loadName() }. Delegowane właściwości są podstawą delegatów ViewModel (by viewModels()). IT Sectr zaleca lazy do opóźnionej inicjalizacji i Delegates.observable do obserwowania zmian.

Funkcja Opis Przykład
reifiedZachowanie typu generycznego w inlineinline fun <reified T> parse(): T
destructuringRozpakowanie data classval (name, age) = person
typealiasAlias typutypealias Orders = List<Order>
lateinitOpóźniona inicjalizacja varlateinit var adapter: Adapter
lazyLeniwa inicjalizacja valval config by lazy { load() }
delegatedDelegowanie właściwościvar x by Delegates.observable(0)

reified — dla bezpiecznych typowo API. lazy — dla opóźnionego ładowania. delegated properties — do ponownego wykorzystania logiki właściwości. IT Sectr zaleca opanowanie wszystkich tych funkcji dla efektywnego programowania w Kotlinie.

Flow i StateFlow

Flow — zimny asynchroniczny strumień danych w Kotlinie. Emituje wartości na żądanie kolektora. StateFlow — gorący Flow z pojedynczą bieżącą wartością. Używany w ViewModel dla UI State. SharedFlow — gorący Flow dla zdarzeń (zdarzenia jednorazowe). flowOf, asFlow — tworzenie Flow z kolekcji. catch, retry, debounce — operatory. stateIn, shareIn — konwersja zimnego Flow na gorący. IT Sectr zaleca StateFlow dla UI State i SharedFlow dla zdarzeń (Snackbar, nawigacja).

kotlin
class SearchViewModel : ViewModel() {
    private val _query = MutableStateFlow("")
    val suggestions: StateFlow<List<String>> = _query
        .debounce(300)
        .filter { it.length >= 2 }
        .flatMapLatest { repository.search(it) }
        .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList())

    fun onQueryChanged(query: String) {
        _query.value = query
    }
}

Serializacja (kotlinx.serialization, Parcelize)

kotlinx.serialization — biblioteka Kotlin do serializacji JSON. @Serializable — adnotacja. @SerialName — niestandardowa nazwa pola. Obsługuje: JSON, CBOR, ProtoBuf. Parcelize — @Parcelize dla Android Parcelable (bez ręcznej implementacji). Gson vs Moshi vs kotlinx: kotlinx.serialization — Kotlin-first, bezpieczny kompilacyjnie, bez refleksji. Moshi — adnotacje + codegen. IT Sectr zaleca kotlinx.serialization dla nowych projektów i Moshi dla istniejących.

kotlin
@Serializable
data class ApiResponse<T>(
    val success: Boolean,
    @SerialName("data") val data: T? = null,
    val error: String? = null
)

@Serializable
data class User(
    val id: Int,
    val name: String,
    val email: String
)

// Deserializacja
val json = Json { ignoreUnknownKeys = true }
val response = json.decodeFromString<ApiResponse<List<User>>>(jsonString)
println("Users: ${response.data?.size ?: 0}")

Często zadawane pytania

Jaka jest różnica między data class a sealed class?

data class — dla danych (automatyczne generowanie equals/hashCode/copy). sealed class — dla hierarchii typów (sprawdzanie w when). sealed interface — to samo z wielodziedziczeniem.

Czym są scope functions w Kotlinie?

let, run, with, apply, also. Różnią się kontekstem (it vs this) i wartością zwracaną (result vs context). let — null safety, apply — konfiguracja, also — efekty uboczne.

Czym jest CoroutineScope i jakie są typy?

CoroutineScope — zakres korutyn. lifecycleScope — dla Activity, viewModelScope — dla ViewModel. GlobalScope — niezalecany.

Czym jest reified w Kotlinie?

reified — zachowanie typu w funkcjach inline. Pozwala na T::class i is T. Działa tylko z funkcjami inline.

Czym są coroutine builders: launch, async, runBlocking?

launch — bez wyniku. async — z wynikiem (Deferred). runBlocking — blokujący most dla main/test. withContext — zmiana Dispatcher.

Podsumowanie

  • data class — dla modeli. sealed class — dla stanów. object — dla singletonów.
  • Scope functions: let (null-safe), apply (konfiguracja), run (obliczenia), also (logowanie).
  • Korutyny: launch (fire-and-forget), async (z wynikiem), withContext (zmiana Dispatcher).
  • viewModelScope — standard dla ViewModel. lifecycleScope — dla Activity/Fragment.
  • reified — bezpieczne typowo funkcje inline. lateinit — DI, lazy — leniwa inicjalizacja.
  • Extension functions — dodawaj funkcjonalność bez dziedziczenia.
  • Dispatchers: Main (UI), IO (sieć/dysk), Default (CPU). Wybierz odpowiedni.

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt