Constantes em Kotlin: pare de adivinhar, comece a usar corretamente
\n\nSe você programa em Kotlin há pelo menos uma semana, certamente já se deparou com a pergunta: "Como declarar uma constante corretamente?" Parece simples — existe val, existe const val, existe companion object. Mas o diabo, como sempre, está nos detalhes. E essa pergunta no Stack Overflow acumulou milhares de visualizações por um motivo.
Vamos entender de uma vez por todas quais formas de criar constantes existem em Kotlin, quando usar cada uma e por que val nem sempre é uma constante. Vamos lá!
1. val vs const val: qual é a diferença?
\n\nA pergunta mais comum de iniciantes: "Eu escrevi val — isso é uma constante?" Resposta: sim e não.
val é uma referência imutável (somente leitura). Mas o valor é calculado em tempo de execução. Ou seja, não é uma constante de tempo de compilação.
// Isso NÃO é uma constante de tempo de compilação\nval currentTime = System.currentTimeMillis()\n\nconst val é uma constante real, que é incorporada ao código em tempo de compilação (como static final em Java).
// Já isso é uma constante\nconst val PI = 3.14159\n\nLimitação importante: const val só pode ser usado com tipos primitivos e String. Nada de objetos, listas ou classes personalizadas.
💡 Regra de ouro: Se o valor é conhecido em tempo de compilação — use const val. Se é calculado em tempo de execução — use val.
2. Onde declarar constantes? Top 3 formas
\n\nForma 1: Constantes top-level (recomendada)
\n\nA forma mais simples e limpa — declarar a constante no nível superior do arquivo. Sem classes, sem objetos — apenas um arquivo com constantes.
\n\n// Constants.kt\nconst val BASE_URL = "https://api.example.com"\nconst val TIMEOUT_SECONDS = 30\nconst val APP_NAME = "MyKotlinApp"\n\nPor que isso é bom?
\n- \n
- Mínimo de código \n
- Acessível de qualquer lugar sem prefixos \n
- O compilador incorpora os valores \n
- Fácil de refatorar \n
Forma 2: companion object dentro da classe
\n\nAbordagem clássica do Java que foi trazida para o Kotlin. Use quando as constantes estão logicamente relacionadas à classe.
\n\nclass NetworkClient {\n companion object {\n const val DEFAULT_PORT = 8080\n const val PROTOCOL = "https"\n }\n}\n\n// Uso\nval port = NetworkClient.DEFAULT_PORT\n\nDesvantagem: ruído sintático. Vantagem: constantes vinculadas ao contexto.
\n\nForma 3: object (singleton) para grupos de constantes
\n\nQuando há muitas constantes e é necessário agrupá-las por significado.
\n\nobject AppConstants {\n const val MAX_LOGIN_ATTEMPTS = 5\n const val SESSION_DURATION = 3600L\n const val DATE_FORMAT = "yyyy-MM-dd"\n\n object Urls {\n const val LOGIN = "/auth/login"\n const val LOGOUT = "/auth/logout"\n }\n}\n\n// Uso\nAppConstants.Urls.LOGIN\n\n3. Constantes no Android: particularidades
\n\nSe você programa para Android, existem alguns detalhes adicionais.
\n\nConstantes em companion object e @JvmStatic
\n\nPara que uma constante de companion object se torne verdadeiramente estática em Java (por exemplo, para anotações), use @JvmStatic:
class MyFragment : Fragment() {\n companion object {\n @JvmStatic\n const val ARG_ID = "id"\n }\n}\n\nConstantes em recursos
\n\nNão se esqueça da forma clássica do Android — recursos. Para strings, cores, dimensões:
\n\n// strings.xml\n<string name="app_name">MyApp</string>\n\n// No código\nval appName = getString(R.string.app_name)\n\nMas isso não são constantes de tempo de compilação.