---
title: "Extension Functions em Kotlin Tutorial em Português — Passo a Passo | Kotlin Brasil"
url: "https://kotlin.dev.br/tutoriais/extension-functions-tutorial/"
markdown_url: "https://kotlin.dev.br/tutoriais/extension-functions-tutorial.MD"
description: "Aprenda Extension Functions em Kotlin com exemplos práticos: sintaxe, propriedades, nullable receivers, generics e casos de uso reais neste tutorial."
date: "2025-06-22"
author: "Karina Melo"
---

# Extension Functions em Kotlin Tutorial em Português — Passo a Passo | Kotlin Brasil

Aprenda Extension Functions em Kotlin com exemplos práticos: sintaxe, propriedades, nullable receivers, generics e casos de uso reais neste tutorial.


Neste tutorial, você vai aprender tudo sobre **Extension Functions em Kotlin** — um dos recursos mais elegantes da linguagem. Extension functions permitem adicionar novas funcionalidades a classes existentes sem precisar herdar delas ou usar padrões como Decorator. Ao final, você vai dominar a sintaxe, entender extension properties, trabalhar com nullable receivers, generics e aplicar esse conhecimento em casos de uso práticos do dia a dia.

## O que São Extension Functions?

Uma [extension function](/glossario/extension-function/) é uma função que "estende" uma classe existente com um novo comportamento, sem modificar o código-fonte original da classe. Isso é particularmente útil quando você quer adicionar métodos a classes que não controla, como classes da standard library do Kotlin, do Android SDK ou de bibliotecas de terceiros.

Em Java, o equivalente seria criar classes utilitárias estáticas (como `StringUtils`, `CollectionUtils`). Em Kotlin, extension functions oferecem uma abordagem muito mais natural e legível.

## Sintaxe Básica

A sintaxe de uma extension function coloca o tipo que está sendo estendido (chamado de **receiver type**) antes do nome da função:

```kotlin
fun String.contarPalavras(): Int {
    return this.trim().split("\\s+".toRegex()).size
}

fun main() {
    val texto = "Kotlin e uma linguagem incrível"
    println(texto.contarPalavras()) // 5

    // Funciona com qualquer String
    println("Hello World".contarPalavras()) // 2
}
```

Dentro da extension function, a palavra `this` se refere ao objeto receiver — neste caso, a instância de `String` na qual a função foi chamada. Você pode omitir `this` ao acessar membros do receiver, assim como faria dentro de uma função membro normal da classe.

```kotlin
fun String.primeiraMaiuscula(): String {
    if (isEmpty()) return this
    return this[0].uppercase() + substring(1).lowercase()
}

println("kotlin".primeiraMaiuscula()) // Kotlin
println("BRASIL".primeiraMaiuscula()) // Brasil
```

## Extension Properties

Além de funções, você pode criar **extension properties**. A única restrição é que elas não podem ter backing field — ou seja, não podem armazenar estado. Elas precisam ser definidas com `get()` (e opcionalmente `set()`):

```kotlin
val String.primeiraLetra: Char
    get() = this[0]

val String.ultimaLetra: Char
    get() = this[length - 1]

val List<Int>.media: Double
    get() = if (isEmpty()) 0.0 else sum().toDouble() / size

fun main() {
    println("Kotlin".primeiraLetra) // K
    println("Kotlin".ultimaLetra)   // n

    val notas = listOf(8, 7, 9, 10, 6)
    println("Média: ${notas.media}") // Média: 8.0
}
```

Extension properties são ótimas para criar acessos legíveis a dados derivados. O código fica muito mais fluente do que chamar funções utilitárias.

## Extensions em Companion Objects

Você pode estender o [companion object](/glossario/companion-object/) de uma classe, permitindo criar o equivalente a métodos estáticos via extensão:

```kotlin
class Usuario(val nome: String, val email: String) {
    companion object
}

fun Usuario.Companion.fromCsv(csv: String): Usuario {
    val partes = csv.split(",")
    return Usuario(partes[0].trim(), partes[1].trim())
}

fun main() {
    val usuario = Usuario.fromCsv("Ana Silva, ana@email.com")
    println("${usuario.nome} — ${usuario.email}")
    // Ana Silva — ana@email.com
}
```

Isso é especialmente útil para criar factory methods para classes de bibliotecas externas que já possuem um companion object definido.

## Escopo de Extension Functions

Extension functions são resolvidas **estaticamente**, não dinamicamente. Isso significa que a função chamada é determinada pelo tipo declarado da variável, não pelo tipo real em tempo de execução:

```kotlin
open class Animal
class Cachorro : Animal()

fun Animal.descricao() = "Eu sou um animal"
fun Cachorro.descricao() = "Eu sou um cachorro"

fun imprimir(animal: Animal) {
    println(animal.descricao())
}

fun main() {
    imprimir(Cachorro()) // "Eu sou um animal" — NÃO "Eu sou um cachorro"!
}
```

Esse comportamento é diferente de sobrescrita de métodos em classes (polimorfismo). É fundamental entender essa distinção para evitar bugs sutis.

Além disso, se uma extension function tem a mesma assinatura que uma função membro da classe, **a função membro sempre vence**:

```kotlin
class MinhaClasse {
    fun saudacao() = "Olá do membro!"
}

fun MinhaClasse.saudacao() = "Olá da extensão!"

fun main() {
    println(MinhaClasse().saudacao()) // "Olá do membro!"
}
```

## Nullable Receiver Extensions

Você pode definir extension functions em tipos [nullable](/glossario/nullable/), o que permite chamá-las mesmo quando o objeto é `null`:

```kotlin
fun String?.ouPadrao(padrao: String = "N/A"): String {
    return this ?: padrao
}

fun Any?.descricaoSegura(): String {
    return this?.toString() ?: "null"
}

fun main() {
    val nome: String? = null
    println(nome.ouPadrao())           // N/A
    println(nome.ouPadrao("Anônimo"))  // Anônimo

    val valor: Int? = null
    println(valor.descricaoSegura())   // null
    println(42.descricaoSegura())      // 42
}
```

Esse padrão é muito poderoso para criar APIs seguras que lidam com nullability de forma elegante, sem poluir o código com verificações `if (x != null)` por toda parte.

## Generic Extensions

Combinando extension functions com [generics](/glossario/generics/), você pode criar funções extremamente reutilizáveis:

```kotlin
fun <T> List<T>.segundoOuNull(): T? {
    return if (size >= 2) this[1] else null
}

fun <T : Comparable<T>> List<T>.estaOrdenada(): Boolean {
    for (i in 0 until size - 1) {
        if (this[i] > this[i + 1]) return false
    }
    return true
}

fun <K, V> Map<K, V>.imprimir() {
    forEach { (chave, valor) ->
        println("$chave -> $valor")
    }
}

fun main() {
    val numeros = listOf(10, 20, 30)
    println(numeros.segundoOuNull()) // 20
    println(numeros.estaOrdenada())  // true

    val vazio = emptyList<String>()
    println(vazio.segundoOuNull())   // null

    mapOf("nome" to "Ana", "cidade" to "SP").imprimir()
}
```

## Casos de Uso Práticos

### Formatação de dados

```kotlin
fun Double.formatarMoeda(): String {
    return "R$ ${"%.2f".format(this).replace(".", ",")}"
}

fun Long.formatarCpf(): String {
    val s = this.toString().padStart(11, '0')
    return "${s.substring(0,3)}.${s.substring(3,6)}.${s.substring(6,9)}-${s.substring(9)}"
}

println(1599.90.formatarMoeda()) // R$ 1599,90
println(12345678901L.formatarCpf()) // 123.456.789-01
```

### Validações

```kotlin
fun String.ehEmailValido(): Boolean {
    return matches(Regex("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$"))
}

fun String.ehCepValido(): Boolean {
    return matches(Regex("^\\d{5}-?\\d{3}$"))
}

println("ana@email.com".ehEmailValido()) // true
println("01310-100".ehCepValido())       // true
```

### Simplificando Android com extensions

```kotlin
// Exemplo típico de extension para desenvolvimento Android
fun Context.toast(mensagem: String, duracao: Int = Toast.LENGTH_SHORT) {
    Toast.makeText(this, mensagem, duracao).show()
}

fun View.visivel() { visibility = View.VISIBLE }
fun View.invisivel() { visibility = View.GONE }

// Uso na Activity:
// toast("Salvo com sucesso!")
// meuBotao.invisivel()
```

### DSL (Domain-Specific Language)

Extension functions são a base para criar [DSLs](/glossario/dsl/) em Kotlin:

```kotlin
class HtmlBuilder {
    private val elementos = mutableListOf<String>()

    fun p(texto: String) { elementos.add("<p>$texto</p>") }
    fun h1(texto: String) { elementos.add("<h1>$texto</h1>") }

    fun construir(): String = elementos.joinToString("\n")
}

fun html(bloco: HtmlBuilder.() -> Unit): String {
    val builder = HtmlBuilder()
    builder.bloco()
    return builder.construir()
}

val pagina = html {
    h1("Bem-vindo ao Kotlin Brasil")
    p("Aprenda Kotlin em português.")
    p("Tutoriais, glossário e muito mais.")
}
println(pagina)
```

## Erros Comuns

1. **Esperar comportamento polimórfico**: extension functions são resolvidas estaticamente. Se você precisa de polimorfismo, use funções membro com `override` em vez de extensions.

2. **Abusar de extension functions**: nem tudo precisa ser uma extension. Use-as quando fizer sentido semântico — quando a função realmente "pertence" ao tipo. Funções utilitárias genéricas podem ser funções top-level normais.

3. **Esquecer que membros vencem extensions**: se a classe já tem um método com a mesma assinatura, sua extension será ignorada silenciosamente. Sempre verifique a API da classe antes de criar uma extension.

4. **Não importar extensions de outros arquivos**: extension functions definidas em outros pacotes precisam ser importadas com `import`. Se a sua extension não está disponível, verifique os imports.

5. **Tentar armazenar estado em extension properties**: extension properties não podem ter backing field. Se você precisa associar dados extras a um objeto, considere usar um `Map` externo ou o padrão de [delegation](/glossario/delegation/).

## Conclusão e Próximos Passos

Extension functions são um dos recursos que tornam Kotlin tão expressivo e agradável de usar. Elas permitem criar código legível, modular e reutilizável sem modificar classes existentes. Neste tutorial, cobrimos a sintaxe básica, extension properties, companion object extensions, escopo e resolução estática, nullable receivers, generics e diversos casos de uso práticos.

Para aprofundar seus conhecimentos, explore os seguintes tópicos:

- [Lambdas](/tutoriais/lambdas-kotlin/) para combinar com extension functions em APIs fluentes
- [Data Classes](/tutoriais/data-classes-tutorial/) para entender melhor as classes que você pode estender
- [Generics](/tutoriais/generics-kotlin/) para criar extensions ainda mais flexíveis
- [DSLs](/glossario/dsl/) para aprender como extension functions são usadas para criar linguagens de domínio específico

Comece criando extensions simples para tipos que você usa com frequência e, com o tempo, você vai desenvolver um estilo de código Kotlin verdadeiramente idiomático.
