Magia do Kotlin: O que a palavra-chave `by` faz e como ela simplifica o código?

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: Um pequeno operador — uma grande magia

\n\n

Você já olhou para o código de outra pessoa em Kotlin e viu uma construção estranha como val name by lazy { ... } ou class Derived(Base by impl)? Se sim, você certamente se perguntou: «O que a palavra-chave by faz em Kotlin?». Esta pergunta é uma das mais populares no Stack Overflow, e não é à toa. by não é apenas açúcar sintático, mas um poderoso mecanismo de delegação que pode simplificar drasticamente seu código, torná-lo mais limpo e eliminar toneladas de código boilerplate.

\n\n

Neste artigo, vamos analisar by de ponta a ponta. Você aprenderá como funcionam a delegação de propriedades (property delegation) e a delegação de classes (class delegation). Responderemos às perguntas mais frequentes de iniciantes e mostraremos exemplos reais que você pode aplicar imediatamente em seus projetos. Vamos lá!

\n\n

O que é delegação em Kotlin? (A ideia principal)

\n\n

Antes de mergulharmos nos detalhes, vamos entender a essência. Delegação é um padrão de design no qual um objeto transfere a execução de sua tarefa para outro objeto auxiliar. O Kotlin incorporou esse padrão diretamente na linguagem usando a palavra-chave by. Em vez de escrever o código "manualmente", você diz ao compilador: «Ei, deixe essa coisa fazer tudo por mim».

\n\n

Em Kotlin, existem dois tipos principais de delegação:

\n
    \n
  • Delegação de propriedades — quando o getter/setter de uma propriedade é passado para outro objeto.
  • \n
  • Delegação de classes — quando a implementação de uma interface é passada para outro objeto.
  • \n
\n\n

Ambas as opções usam a mesma palavra-chave — by. Vamos analisar cada uma.

\n\n

1. Delegação de propriedades (Property Delegation): by para campos

\n\n

Este é o uso mais popular de by. Ele permite reutilizar a lógica para getters e setters de propriedades. Em vez de escrever código repetitivo toda vez, você usa delegados prontos ou personalizados.

\n\n

Exemplo 1: by lazy — inicialização preguiçosa

\n\n

Imagine que você tem uma propriedade que demora para ser criada (por exemplo, carregar dados da rede). Você não quer calculá-la ao criar a classe, mas sim no primeiro acesso. by lazy faz exatamente isso:

\n\n
val heavyData: String by lazy {\n    println("Calculando dados...")\n    "Resultado muito pesado"\n}\n\nfun main() {\n    println("Início")\n    println(heavyData) // Primeiro acesso: calcula\n    println(heavyData) // Segundo acesso: apenas pega do cache\n}
\n\n

Saída:

\n
Início\nCalculando dados...\nResultado muito pesado\nResultado muito pesado
\n\n

O que aconteceu aqui? A palavra-chave by diz: «A propriedade heavyData delega sua implementação ao objeto lazy { ... }». Esse objeto garante que o bloco de código será executado apenas uma vez, no primeiro acesso, e então armazenará o resultado. Isso é ideal para configurações, conexões de banco de dados e outros objetos "caros".

\n\n

Exemplo 2: by observable — monitorando mudanças

\n\n

Quer executar alguma ação toda vez que uma propriedade muda? Use Delegates.observable da biblioteca padrão:

\n\n
import kotlin.properties.Delegates\n\nvar watchedValue: Int by Delegates.observable(0) { property, oldValue, newValue ->\n    println("Antigo: $oldValue, Novo: $newValue")\n}\n\nfun main() {\n    watchedValue = 10  // Antigo: 0, Novo: 10\n    watchedValue = 42  // Antigo: 10, Novo: 42\n}
\n\n

Esse padrão é indispensável para programação reativa, validação de dados ou sincronização de UI. A propósito, by aqui funciona exatamente da mesma

Blogs

Book Recommendations