Argumenty domyślne i nazwane

Dwa wygodne mechanizmy Kotlina: wartości domyślne parametrów (fun f(x: Int = 0)) pozwalają pominąć argument przy wywołaniu, a argumenty nazwane (f(x = 5)) czynią wywołania czytelnymi i pozwalają podawać je w dowolnej kolejności.

x: Int = 0 f(x = 5) mniej przeciążeń Lekcja 3.3
1

Wartości domyślne parametrów

Parametrowi można nadać wartość domyślną – zapisujemy ją po znaku = w nagłówku funkcji. Jeśli przy wywołaniu pominiesz ten argument, funkcja użyje wartości domyślnej.

Parametr z wartością domyślną
fun przywitaj(imie: String, powitanie: String = "Cześć") {
    println("$powitanie, $imie!")
}

Tutaj powitanie ma domyślnie wartość "Cześć". Parametr imie domyślnej nie ma, więc trzeba go zawsze podać.

2

Pomijanie argumentów przy wywołaniu

Dzięki wartości domyślnej tę samą funkcję możesz wywołać krócej lub pełniej – zależnie od potrzeb:

Dwa sposoby wywołania
przywitaj("Anna")              // Cześć, Anna!   (użyto domyślnego "Cześć")
przywitaj("Anna", "Witaj")     // Witaj, Anna!   (podano własne powitanie)
Domyślna wartość = sensowny standard

Wartości domyślne wybieraj tak, by pokrywały najczęstszy przypadek. Wtedy w typowym użyciu wywołanie jest krótkie, a rzadsze warianty wciąż są możliwe.

3

Argumenty nazwane

Przy wywołaniu możesz podać nazwę parametru, do którego trafia wartość: nazwa = wartość. To czyni wywołanie czytelniejszym i pozwala ustawiać argumenty w dowolnej kolejności.

Wywołanie z nazwami
przywitaj(imie = "Anna")
przywitaj(imie = "Anna", powitanie = "Hej")

// gdy nazwiemy argumenty, kolejność nie ma znaczenia:
przywitaj(powitanie = "Hej", imie = "Anna")
Nazwy ratują czytelność

Gdy funkcja przyjmuje kilka wartości tego samego typu (np. trzy liczby), rysuj(szerokosc = 80, wysokosc = 25) czyta się o wiele jaśniej niż rysuj(80, 25) – od razu wiadomo, co jest czym.

4

Pomijanie środkowych argumentów

Argumenty nazwane i domyślne grają w parze. Gdy funkcja ma kilka parametrów domyślnych, a chcesz ustawić tylko jeden z dalszych – nazwij go, a resztę zostaw domyślną.

Ustawiamy tylko jeden parametr
fun rysuj(znak: Char = '*', szerokosc: Int = 10, wysokosc: Int = 1) {
    for (w in 1..wysokosc) {
        for (s in 1..szerokosc) print(znak)
        println()
    }
}

rysuj()                       // 1 wiersz z 10 gwiazdek
rysuj(wysokosc = 3)           // pomijamy znak i szerokość, ustawiamy tylko wysokość
rysuj(znak = '#', wysokosc = 2)  // szerokość zostaje domyślna (10)
Bez nazw nie da się „przeskoczyć”

Gdybyś nie nazwał argumentu, Kotlin przypisałby wartości po kolei. Żeby ustawić tylko wysokosc (a pominąć wcześniejsze), nazwa wysokosc = jest konieczna.

5

Mniej przeciążeń

W wielu językach, żeby umożliwić różne zestawy argumentów, pisze się kilka funkcji o tej samej nazwie (tzw. przeciążenia). W Kotlinie zwykle nie trzeba – jedna funkcja z wartościami domyślnymi zastępuje cały zestaw.

❌ Kilka wersji tej samej funkcji

fun loguj(tekst: String) {
    loguj(tekst, "INFO")
}
fun loguj(tekst: String,
          poziom: String) {
    println("[$poziom] $tekst")
}

✅ Jedna funkcja z domyślną

fun loguj(
    tekst: String,
    poziom: String = "INFO"
) {
    println("[$poziom] $tekst")
}
// loguj("Start")
// loguj("Błąd", "ERROR")

Efekt jest ten sam, a kodu mniej – i w jednym miejscu. To jedno z tych miejsc, gdzie Kotlin oszczędza sporo pisania.

6

Zasady i kolejność

  • Parametry z wartościami domyślnymi zwykle umieszczamy na końcu listy parametrów.
  • W wywołaniu argumenty pozycyjne (bez nazwy) podajemy przed nazwanymi.
  • Argumenty nazwane mogą być w dowolnej kolejności względem siebie.
  • Aby pominąć argument ze środka, kolejne musisz nazwać.
Poprawne i ryzykowne mieszanie
fun opis(imie: String, wiek: Int, miasto: String = "-") { /* ... */ }

opis("Anna", 18)                       // OK – pozycyjnie, miasto domyślne
opis("Anna", wiek = 18, miasto = "Lębork")  // OK – pozycyjny, potem nazwane
7

Częste błędy

❌ Błąd 1: pominięcie środkowego bez nazwy

❌ Wartość trafia nie tam

fun rysuj(znak: Char = '*',
          wysokosc: Int = 1) {}
rysuj(3)
// 3 trafia do znak, nie do
// wysokosc -> błąd typu

✅ Nazwij argument

fun rysuj(znak: Char = '*',
          wysokosc: Int = 1) {}
rysuj(wysokosc = 3)

❌ Błąd 2: literówka w nazwie argumentu

❌ Nazwa nie pasuje do parametru

przywitaj(imię = "Anna")
// Błąd! parametr nazywa się
// imie, nie imię

✅ Dokładna nazwa parametru

przywitaj(imie = "Anna")

❌ Błąd 3: parametr wymagany po domyślnym

❌ Domyślny przed wymaganym

fun f(a: Int = 0, b: Int) {}
f(5)
// 5 trafia do a, a b zostaje
// bez wartości -> błąd

✅ Domyślne na końcu

fun f(b: Int, a: Int = 0) {}
f(5)
// b = 5, a = 0

❌ Błąd 4: pozycyjny po nazwanym

❌ Mieszanie w złej kolejności

opis(imie = "Anna", 18)
// ryzykowne – pozycyjny
// po nazwanym bywa błędem

✅ Najpierw pozycyjne, potem nazwane

opis("Anna", wiek = 18)
8

Podsumowanie

  • Parametr może mieć wartość domyślną: fun f(x: Int = 0) – wtedy argument można pominąć.
  • Wartości domyślne dobieraj tak, by pokrywały najczęstszy przypadek.
  • Argumenty nazwane (f(x = 5)) poprawiają czytelność i pozwalają na dowolną kolejność.
  • Aby pominąć argument ze środka listy, kolejne trzeba nazwać.
  • Jedna funkcja z domyślnymi zastępuje wiele przeciążeń (kilku wersji tej samej funkcji).
  • Zasady: domyślne zwykle na końcu; w wywołaniu pozycyjne przed nazwanymi.
9

Zadania do wykonania

Zadania wykonaj w Kotlin Playground (play.kotlinlang.org).

Zadanie 1 łatwe

Napisz funkcję przywitaj(imie: String, powitanie: String = "Cześć"). Wywołaj ją raz bez podawania powitania i raz z własnym.

Zadanie 2 łatwe

Wywołaj funkcję z zadania 1, używając argumentów nazwanych i podając je w odwrotnej kolejności (najpierw powitanie, potem imię).

Zadanie 3 łatwe

Napisz funkcję rysujLinie(znak: Char = '-', dlugosc: Int = 20), która wypisuje linię z powtórzonego znaku. Wywołaj ją: domyślnie, z własną długością oraz z własnym znakiem podanym przez nazwę.

Zadanie 4 średnie

Napisz funkcję opisProduktu(nazwa: String, cena: Double, waluta: String = "zł", rabat: Int = 0), która wypisuje opis produktu. Wywołaj ją na kilka sposobów: z samą nazwą i ceną, z innym rabatem (pomijając walutę przez nazwę argumentu) oraz z pełnym zestawem wartości. Zwróć uwagę, że jedna funkcja obsłużyła wszystkie warianty.