Rozšiřující funkce v Kotlin: co to je, syntaxe a použití

Autor: IT Sectr Publikováno: 2026-06-21 Doba čtení: 9 min

rozšiřující funkce — mechanismus Kotlin, který umožňuje přidávat nové metody k existujícím třídám bez dědičnosti a bez změny zdrojového kódu. Funkce je deklarována s prefixem ve formě typu-příjemce a volána jako běžná metoda tohoto typu. Podle Kotlin Documentation, 2025 jsou rozšiřující funkce kompilovány do statických metod s prvním parametrem-příjemcem, což zaručuje nulovou režii za běhu ve srovnání s běžnými voláními.

Hlavní body

  • Rozšiřující funkce — metoda s typem příjemce, volaná jako člen třídy bez dědičnosti
  • Typ příjemce je uveden tečkou před názvem funkce: fun Type.method()
  • Statická dispečink — rozšiřující funkce není virtuální, volá se podle typu proměnné
  • Import je povinný: rozšiřující funkce nejsou členy třídy a vyžadují import
  • Členové třídy mají prioritu: pokud se metoda shoduje — volá se člen třídy, nikoli rozšíření

Co je rozšiřující funkce v Kotlin?

Rozšiřující funkce je funkce deklarovaná mimo třídu, ale volaná jako její metoda. Přijímá typ-příjemce, ke kterému je přidána nová metoda. Uvnitř funkce klíčové slovo this odkazuje na instanci typu příjemce. Tento přístup umožňuje rozšíření finálních tříd, tříd knihoven třetích stran a dokonce primitivních typů bez vytváření obálek.

Na rozdíl od Javy, kde přidání metody k existující třídě vyžaduje buď dědičnost, nebo statickou pomocnou třídu, Kotlin nabízí elegantní řešení bez boilerplate. Podle údajů výzkumu Kotlin Foundation (2024) patří rozšiřující funkce mezi pět nejčastěji používaných funkcí jazyka — 78 % Kotlin vývojářů je používá v každodenní práci.

Kompilátor Kotlin převádí rozšiřující funkci na statickou metodu, kde je instance příjemce předána jako první argument. To znamená, že rozšiřující funkce nemění bajtkód cílové třídy a nenarušují zapouzdření — jsou přístupná pouze veřejná pole a metody příjemce.

Používejte rozšiřující funkce pro psaní čistých pomocných funkcí, které jsou logicky vázány na určitý typ, ale nelze je přidat do jeho zdrojového kódu.

Syntaxe rozšiřující funkce: deklarace a volání

Základní syntaxe rozšiřující funkce: název typu-příjemce, tečka, název funkce, poté parametry a návratový typ. Uvnitř funkce je příjemce přístupný přes this.

kotlin
// Rozšiřující funkce pro String
fun String.isEmail(): Boolean {
    return this.contains("@") && this.contains(".")
}

// Volána jako běžná metoda String
val result = "user@example.com".isEmail() // true

V tomto příkladu se isEmail() stává dostupným pro všechny řetězce. Uvnitř funkce je this samotný řetězec, na kterém je metoda volána. Kotlin umožňuje vynechat this ve většině případů — lze jednoduše napsat contains("@") místo this.contains("@").

Rozšiřující funkce s parametry

Rozšiřující funkce mohou přijímat další parametry a vracet hodnoty libovolného typu. To z nich dělá plnohodnotné funkce, nejen syntaktický cukr.

kotlin
fun List<Int>.defaultIfEmpty(default: Int): List<Int> {
    if (this.isEmpty()) return listOf(default)
    return this
}

val populated = listOf(1, 2).defaultIfEmpty(0)
val empty = listOf<Int>().defaultIfEmpty(0)

Parametr default určuje hodnotu vrácenou pro prázdný seznam. Rozšiřující funkce může být generická — typ List je zobecněný, i když v příkladu je použita konkrétní List.

Statická dispečink a příjemce

Rozšiřující funkce v Kotlin používají statickou dispečink, nikoli virtuální. To je klíčový rozdíl od běžných metod tříd. Která rozšiřující funkce bude volána, se určuje ve fázi kompilace podle statického typu proměnné, nikoli podle jejího skutečného typu za běhu.

kotlin
open class Animal
class Dog : Animal()

fun Animal.speak() = "Zvuk zvířete"
fun Dog.speak() = "Štěkot"

fun test() {
    val animal: Animal = Dog()
    println(animal.speak()) // „Zvuk zvířete" — statický typ Animal

    val dog: Dog = Dog()
    println(dog.speak()) // „Štěkot" — statický typ Dog
}

Přestože proměnná animal ukazuje na instanci Dog, volá se rozšiřující funkce pro Animal, protože statický typ proměnné je Animal. Pokud by speak() byla virtuální metoda třídy, volalo by se Dog.speak(). Tato vlastnost je důležitá při navrhování API založeného na rozšiřujících funkcích.

Import a oblast viditelnosti rozšiřujících funkcí

Rozšiřující funkce nejsou členy třídy — jsou to běžné funkce, které vyžadují import pro použití v jiném souboru. Kotlin nabízí dvě varianty importu: podle názvu funkce nebo s přejmenováním.

kotlin
// Import podle názvu
import com.example.extensions.isEmail

// Import s aliasem (pro řešení konfliktů)
import com.example.extensions.isEmail as isValidEmail

// Volání po importu
val valid = "test@test.com".isEmail()

Přejmenování pomocí as je užitečné při konfliktech názvů — například pokud dvě knihovny poskytují rozšiřující funkci se stejným názvem pro stejný typ. V tomto případě lze jednu z nich importovat pod jiným názvem a volat přes nový název.

Oblast viditelnosti

Rozšiřující funkce lze deklarovat na různých úrovních:

ÚroveňViditelnostPříklad
Top-levelCelý projekt po importufun String.isEmail()
Member extensionUvnitř třídy vlastníkaclass A { fun B.ext() }
LocalUvnitř funkcefun test() { fun String.ext() }

Member extension functions — zvláštní případ, kdy je rozšiřující funkce deklarována uvnitř jiné třídy. V tomto případě jsou uvnitř rozšiřující funkce přístupní jak příjemce (this funkce), tak členové vnější třídy.

Priorita členů třídy nad rozšířeními

Pokud má třída metodu se stejným podpisem jako rozšiřující funkce, vždy se volá člen třídy. Rozšiřující funkce nikdy nepřepisuje metodu třídy — to je architektonické rozhodnutí pro zabránění náhodným přepsáním.

kotlin
class User {
    fun greet() = "Ahoj z třídy"
}

fun User.greet() = "Hello from extension"

fun main() {
    val user = User()
    println(user.greet()) // „Ahoj z třídy"
}

I když je rozšiřující funkce definována později a má stejný podpis, kompilátor vybere metodu třídy. Kompilátor Kotlin vydá varování při detekci takové situace. Jediný způsob, jak zavolat rozšiřující funkci při existenci metody třídy, je obrátit se na ni jako na běžnou funkci: greet(user).

Praktické příklady rozšiřujících funkcí

Ve vývoji pro Android se rozšiřující funkce staly standardním nástrojem pro práci s View, Context a fragmenty. Knihovna Android KTX je postavena na rozšiřujících funkcích a poskytuje pohodlné obálky pro Android API.

kotlin
// Rozšiřující funkce pro práci s View
fun View.show() {
    visibility = View.VISIBLE
}

fun View.hide() {
    visibility = View.GONE
}

// Rozšiřující funkce pro Context — toast
fun Context.toast(message: String) {
    Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}

// Rozšiřující funkce jako stavitel DSL
fun String.colorFormat(color: String): String =
    "$color$this\u001b[0m"

Rozšiřující funkce toast() činí volání závislá na Context stručnými: místo psaní Toast.makeText(context, message, length).show() stačí napsat context.toast("Text"). To snižuje boilerplate a činí kód čitelnějším.

Často kladené otázky

Lze přepsat rozšiřující funkci v podtřídě?

Ne, rozšiřující funkce používají statickou dispečink. Pokud deklarujete rozšiřující funkci pro základní třídu a stejnou pro podtřídu, která z nich bude volána, určuje statický typ proměnné ve fázi kompilace, nikoli skutečný typ za běhu.

Jak fungují rozšiřující funkce s nullable typy?

Lze deklarovat rozšiřující funkce pro nullable typy příjemce: fun String?.isNullOrEmail(). Uvnitř takové funkce může být this null, proto je nutné použít operátory bezpečného volání nebo explicitní kontrolu null.

Mají rozšiřující funkce režii výkonu?

Ne, rozšiřující funkce jsou kompilovány do statických metod. Na úrovni bajtkódu je volání rozšiřující funkce totožné s voláním statické metody s prvním parametrem-příjemcem. Žádná reflexe nebo dynamická dispečink.

Lze deklarovat rozšiřující vlastnost pro třídu?

Ano, rozšiřující vlastnosti fungují podobně jako rozšiřující funkce, ale nemohou ukládat stav — pouze getter a setter. Například: val List<Int>.sum get() = reduce(Int::plus). Jsou také kompilovány do statických getter/setter metod.

Čím se liší rozšiřující funkce od metod v Java pomocných třídách?

V Javě píšete StringUtils.isEmail(str), v Kotlin — str.isEmail(). Rozdíl není jen v syntaxi: rozšiřující funkce podporují automatické doplňování v IDE, zlepšují čitelnost řetězců volání a umožňují IDE navrhovat relevantní funkce pro konkrétní typ. V Javě takové možnosti neexistují.

Shrnutí

  • Rozšiřující funkce — metoda s typem příjemce, volaná jako člen třídy bez dědičnosti
  • Statická dispečink — výběr funkce podle statického typu, nikoli typu za běhu
  • Nulová režie — kompilována do statické metody s příjemcem jako prvním parametrem
  • Import povinný pro použití v jiných souborech, alias možný pomocí as
  • Členové třídy mají prioritu před rozšiřujícími funkcemi se stejným podpisem
  • Member extensions — rozšíření deklarovaná uvnitř třídy, mají přístup k jejím členům
  • Praktické použití — nástroje pro String, View, Context, kolekce a stavbu DSL

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také