DEV Community

Isaias Velasquez
Isaias Velasquez

Posted on

How to usar extension functions no Kotlin

Extension functions sao uma das features do Kotlin que mais uso no dia a dia. Elas permitem adicionar metodos a classes sem precisar herdar delas.

A sintaxe e simples. Voce escreve o nome da classe seguido de ponto e o nome da funcao:

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

println("teste@email.com".isEmail()) // true
println("invalido".isEmail())         // false
Enter fullscreen mode Exit fullscreen mode

Repare que this dentro da extension function se refere a instancia da String.

Para arquivos com multiplas extensions, crie um arquivo separado como StringExtensions.kt:

// StringExtensions.kt
fun String.limparEspacos(): String = this.trim().replace(Regex("\\s+"), " ")
fun String.truncar(max: Int): String = if (length <= max) this else substring(0, max) + "..."
Enter fullscreen mode Exit fullscreen mode

Uso:

val texto = "  texto   com   espacos   " 
println(texto.limparEspacos()) // "texto com espacos"
println("Mensagem muito longa aqui".truncar(10)) // "Mensagem m..."
Enter fullscreen mode Exit fullscreen mode

Extension functions tambem funcionam com generics. Um exemplo pratico para listas:

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

val lista = listOf("a", "b", "c")
println(lista.segundoOuNull()) // "b"
println(listOf("unico").segundoOuNull()) // null
Enter fullscreen mode Exit fullscreen mode

Um padrao util e criar extensions para Android ou Spring que simplificam chamadas repetitivas:

fun RecyclerView.setupAdapter(items: List<Any>, layoutId: Int) {
    adapter = GenericAdapter(items, layoutId)
}

fun SharedPreferences.editar(block: SharedPreferences.Editor.() -> Unit) {
    val editor = edit()
    editor.block()
    editor.apply()
}

preferences.editar {
    putString("nome", "Joao")
    putInt("idade", 30)
}
Enter fullscreen mode Exit fullscreen mode

Nesse ultimo exemplo, block e uma lambda com receiver. O SharedPreferences.Editor vira o this dentro do bloco, e voce chama putString diretamente.

Uma limitacao: extension functions nao sobrescrevem metodos existentes. Se a classe ja tem um metodo com a mesma assinatura, o metodo da classe vence:

class Pessoa(val nome: String)
fun Pessoa.toString(): String = "Pessoa: $nome"

val p = Pessoa("Joao")
println(p.toString()) // Exibe o toString() original da data class, nao a extension
Enter fullscreen mode Exit fullscreen mode

Extension functions sao resolvidas estaticamente, no momento da compilacao. Elas nao sao virtuais. Isso significa que o tipo da variavel decide qual funcao chama:

open class Animal
class Cachorro : Animal()

fun Animal.falar() = "som generico"
fun Cachorro.falar() = "latido"

val animal: Animal = Cachorro()
println(animal.falar()) // "som generico" (tipo estatico e Animal)
Enter fullscreen mode Exit fullscreen mode

That's all for now.
Thanks for reading!

Top comments (0)