Najlepszy sposób na zrozumienie języka to napisanie w nim kodu. Nie czytanie o nim, nie oglądanie webinarów, nie zapisywanie artykułów do „przeczytania później" (wszyscy wiemy, jak to się kończy). Kotlin od zera: tutorial dla początkujących - 1Otworzyć IDE i zbudować coś, co naprawdę działa.

Właśnie do tego służy ten tutorial. Przejdziemy od zera do pierwszej działającej mini-aplikacji. Jeśli znasz Javę, pójdzie jeszcze szybciej — przez cały czas będę pokazywał paralele.

Uruchamianie Kotlina: dwa sposoby, jeden zajmuje zero minut

Prosto w przeglądarce. Wejdź na play.kotlinlang.org i po prostu zacznij pisać. Nic do instalowania, nic do konfigurowania, żadnych Stack Overflow o tym, dlaczego setup nie działa. Idealne na pierwsze spotkanie.

W IntelliJ IDEA. Wsparcie dla Kotlina jest wbudowane. Tworzysz nowy projekt Kotlinowy — i gotowe. Żadnych pluginów, żadnych ceregieli.

Twój pierwszy program:

fun main() {
    println("Hello, Kotlin!")
}

W Javie to samo wygląda tak:

public class Main {
    public static void main(String[] args) {
        System.out.println("Hello, Kotlin!");
    }
}

Oba robią dokładnie to samo. Kotlin po prostu nie ma public static void ani klasy-wrappera, bo... po co nam one były? Dobre pytanie. Java nigdy do końca na nie nie odpowiedziała.

val i var: dwa słowa do zapamiętania

W Kotlinie zmienne deklaruje się przez val albo var.

val name = "Anna"    // Niemutowalna. Jak final w Javie.
var age = 25         // Mutowalna.

age = 26             // Okej.
name = "Piotr"       // Błąd kompilacji.

Prosta zasada: używaj val wszędzie tam, gdzie wartość nie musi się zmieniać. var tylko wtedy, gdy naprawdę potrzebujesz mutacji. To jak złożenie sobie obietnicy z góry: „Tego nie będę zmieniać." I Kotlin pilnuje, żebyś jej dotrzymał.

Typ możesz pominąć — Kotlin sam go wywnioskuje:

val score = 100     // Kotlin rozumie: to jest Int
val name = "Anna"   // To jest String

Albo jawnie, jeśli wolisz:

val score: Int = 100
val name: String = "Anna"

Null-safety: jak Kotlin eliminuje NullPointerException

Tony Hoare wynalazł null w 1965 roku i później nazwał to swoim „błędem wartym miliard dolarów". Brzmi jak samokrytyka, ale szczerze mówiąc — to niedoszacowanie. NullPointerException kosztował branżę znacznie więcej.

W Javie każda zmienna może okazać się nullem. Kompilator milczy. Dowiadujesz się w runtime. Na produkcji. Czasem podczas live demo u klienta — tak, to też się zdarza.

Kotlin rozwiązuje problem na poziomie systemu typów:

var name: String = "Anna"
name = null  // Błąd kompilacji. Od razu. Przed uruchomieniem.

Jeśli zmienna może być nullem, musisz to zaznaczyć jawnie przez ?:

var name: String? = "Anna"
name = null  // Uzgodniliśmy, że nullable — teraz okej.

Co robić, gdy trzeba wywołać metodę na czymś, co może być nullem?

println(name?.length)        // Jeśli null — zwróci null. Nie padnie.
println(name?.length ?: 0)   // Jeśli null — zwróci 0. Operator Elvisa.

Nazywa się operatorem Elvisa — bo ?: przypomina fryzurę Elvisa Presleya. To nie jest żart. To oficjalne wyjaśnienie w dokumentacji.

Funkcje

W Javie:

public static int add(int a, int b) {
    return a + b;
}

W Kotlinie:

fun add(a: Int, b: Int): Int {
    return a + b
}

Albo jeszcze krócej — dla funkcji jednowyrazowych:

fun add(a: Int, b: Int) = a + b

Kotlin obsługuje domyślne wartości parametrów. W Javie pisałbyś kilka przeciążonych metod. W Kotlinie — tylko jedną:

fun greet(name: String, greeting: String = "Cześć") {
    println("$greeting, $name!")
}

greet("Anna")           // Cześć, Anna!
greet("Piotr", "Hej")   // Hej, Piotr!

Szablony stringów — $name bezpośrednio w stringu. Kotlin podstawia wartość zmiennej. Żadnego +, żadnej konkatenacji — jak powinien działać sensowny język.

Data class: żegnaj, boilerplate

Klasyczne zadanie: potrzebny jest model — użytkownik z imieniem, wiekiem i emailem.

W Javie to konstruktor, trzy gettery, trzy settery, equals(), hashCode(), toString(). Albo Lombok. Albo pogodzenie się z losem i pisanie wszystkiego ręcznie jak w 2005 roku.

W Kotlinie:

data class User(val name: String, val age: Int, val email: String)

Jedna linia. Kompilator generuje wszystko pozostałe, w tym copy():

val anna = User("Anna", 30, "anna@example.com")
val olderAnna = anna.copy(age = 31)

println(anna)
// User(name=Anna, age=30, email=anna@example.com)

Spójrz na copy(). Tworzysz nowy obiekt, zmieniając tylko potrzebne pola. W Javie zazwyczaj pisałbyś do tego Buildera. Albo po prostu cierpiał.

Extension functions: dodawanie metod do cudzych klas

Wyobraź sobie, że chcesz dodać metodę do klasy String. W Javie — klasa pomocnicza ze statycznymi metodami i wszędzie StringUtils.doSomething(myString). Działa, ale czuć prowizorkę.

W Kotlinie — extension functions:

fun String.isValidEmail(): Boolean {
    return this.contains("@") && this.contains(".")
}

println("user@example.com".isValidEmail())  // true
println("to-nie-email".isValidEmail())      // false

Wygląda jak natywna metoda klasy. Żadnego dziedziczenia, żadnych wrapperów. Po prostu dodałeś metodę — i już jej używasz.

Składamy wszystko razem: walidator użytkowników

Weźmy to, czego się nauczyliśmy, i napiszmy coś prawdziwego.

data class User(val name: String, val email: String?)

fun String.isValidEmail() = contains("@") && contains(".")

fun validateUser(user: User): String {
    val emailStatus = user.email?.let {
        if (it.isValidEmail()) "poprawny" else "niepoprawny"
    } ?: "nie podano"

    return "${user.name}: email $emailStatus"
}

fun main() {
    val users = listOf(
        User("Anna", "anna@example.com"),
        User("Piotr", "piotr-nie-email"),
        User("Marek", null)
    )
    users.forEach { println(validateUser(it)) }
}

Wynik:

Anna: email poprawny
Piotr: email niepoprawny
Marek: email nie podano

Zwróć uwagę: null jest obsłużony bez jednego if. Operatory ?. i ?: robią to elegancko. Marek nie podał emaila — i żadnego NPE. Życie jest piękne.

To był dopiero początek

Omówiliśmy tu podstawy: zmienne, null-safety, funkcje, data classy, extension functions.

Dalej robi się ciekawiej. Coroutines — asynchroniczny kod bez bólu. Sealed classy — potężna alternatywa dla switch, która nie pozwoli zapomnieć o żadnym przypadku. Funkcyjne operacje na kolekcjach — map, filter, reduce w jednej linii.

Jeśli chcesz uczyć się Kotlina systematycznie, a nie z kawałków artykułów, które giną w zakładkach przeglądarki — spróbuj naszego kursu. 62 poziomy, ponad 1100 zadań z automatycznym sprawdzaniem, 3 projekty do portfolio. Pierwszy poziom jest bezpłatny.

codegym.cc/pl/courses/kotlin

Czytaj dalej