O que é reified em Kotlin e por que é "mágica"?
\nSe você já programou em Java, certamente já se deparou com Type Erasure — o apagamento de tipos em tempo de execução. Em Java (e em Kotlin por padrão), a informação sobre o tipo dentro de genéricos está disponível apenas em tempo de compilação, e em tempo de execução — desaparece. Isso significa que você não pode escrever if (value is T) ou T::class dentro de uma função comum, porque T em tempo de execução é apenas Object.
Mas o Kotlin foi além. A palavra-chave reified (do inglês "reificado") permite "reviver" o tipo dentro de uma função inline. Graças ao reified, você pode fazer o que parecia impossível em Java: verificar o tipo, obter KClass, criar instâncias e até trabalhar com reflexão — tudo em tempo de execução.
Neste artigo, vamos analisar como o reified funciona, com exemplos reais que você pode aplicar imediatamente. Vamos lá!
\n\nProblema: Type Erasure em ação
\nImagine: você está escrevendo uma função que deve verificar se um objeto é uma string. Tentativa ingênua:
\nfun <T> isString(value: Any): Boolean {\n return value is T // Erro de compilação!\n}\nO compilador emitirá um erro: "Cannot check for instance of erased type: T". Por quê? Porque em tempo de execução, a JVM não sabe o que é T. Para ela, T é apenas Object.
O mesmo acontece ao obter a classe: T::class dentro de uma função comum também não funciona. Isso é o Type Erasure — a principal dor de cabeça dos desenvolvedores Java.
Solução: reified + inline
\nKotlin oferece uma saída elegante. Para "lembrar" o tipo em tempo de execução, você precisa tornar a função inline e marcar o parâmetro de tipo com a palavra-chave reified:
\ninline fun <reified T> isString(value: Any): Boolean {\n return value is T // Agora funciona!\n}\nAgora você pode chamar:
\nprintln(isString<String>("Hello")) // true\nprintln(isString<Int>("Hello")) // false\nComo isso funciona? Quando você marca uma função como inline, o compilador insere seu código diretamente no local da chamada. E reified faz o compilador substituir o tipo concreto (por exemplo, String) no lugar de T no código gerado. Como resultado, no bytecode aparece uma verificação explícita value is String.
Exemplos práticos de uso do reified
\nVamos ver alguns cenários reais onde o reified realmente simplifica a vida.
\n\n1. Obtendo a classe em tempo de execução
\nUma das tarefas mais comuns é obter KClass ou Class a partir do parâmetro de tipo. Sem reified, isso é impossível:
inline fun <reified T> getKClass(): KClass<T> = T::class\n\n// Uso:\nval kClass = getKClass<String>()\nprintln(kClass.simpleName) // String\nIsso é especialmente útil ao trabalhar com bibliotecas que exigem reflexão (por exemplo, serialização, ORM, contêineres DI).
\n\n2. Criando uma instância por tipo
\nQuer criar um objeto do tipo desejado sem passar um construtor? Fácil:
\ninline fun <reified T : Any> createInstance(): T {\n return T::class.createInstance()\n}\n\n// Exemplo:\nval instance = createInstance<StringBuilder>()\ninstance.append("Hello, reified!")\nMas cuidado: createInstance() funciona apenas se a classe tiver um construtor sem parâmetros. Caso contrário, você receberá uma exceção.
3. Filtragem por tipo em coleções
\nSuponha que você tenha uma lista de objetos de diferentes tipos e queira filtrar apenas as strings. Na biblioteca padrão do Kotlin existe filterIsInstance<T>(), mas você pode facilmente escrever sua própria versão:
Blogs
Book Recommendations
Leia também