Se tem uma funcionalidade no Kotlin que é usada com muita frequência, mas muitas pessoas não tem ideia do que seja, são as funções de escopo.
fun main() {
val user: User? = findUserById(1)
user?.let {
println(it)
}
}
Conseguiu identificar a função de escopo? Não? Não se preocupe que vamos entendê-las!
Conhecendo as funções de escopo
Basicamente, função de escopo é uma função que executa um bloco de código dentro de um contexto de um objeto! Definição bem abstrata, né? Então vamos para a prática:
user.let {
...
}
Neste código, let
é uma função de escopo que executa no contexto do user
que é do tipo User?
. Dentro deste contexto, temos acesso a user
a partir do parâmetro da lambda, podemos até mesmo mudar o nome:
user.let { u ->
println(u)
}
Usar funções de escopo dessa forma, não tem diferença de apenas chamar println(user)
, concorda? Então porque elas existem?
Safe call com funções de escopo
Uma das maiores utilidades de funções de escopo é combinar com a safe call:
user?.let {
println(it.name)
}
Todo parâmetro único em expressões lambdas são subentendidos como
it
por padrão.
Essa abordagem tem o mesmo resultado de usar um if
que garante que não é nulo. A diferença fica na sintax que é mais sucinta, permitindo até mesmo usar o it
ou um nome que identifica melhor o contexto, como por exemplo, nonNullUser
:
user?.let { nonNullUser ->
println(nonNullUser.name)
}
Variáveis apenas dentro do escopo esperado
Um outro caso que auxilia bastante, é que podemos trabalhar com variáveis que irão existir apenas nas funções de escopo. Se pegarmos a amostra inicial como exemplo, podemos criar a seguinte variação:
findUserById(1)?.let { user ->
println(user.name)
}
Notou a diferença? Com essa abordagem, a existência da variável user
é só dentro de let
! Logo, você não precisa mais se preocupar com nullable ou criar uma variável desnecessária no resto da aplicação.
Retornos em funções de escopo
Outro detalhe interessante, as funções de escopo podem retornar valores diferentes! Se usarmos o let
como exemplo, ele sempre devolve o valor da última instrução, logo, se println()
for a última instrução, será retornado Unit
:
val result: Unit? = findUserById(1)?.let { user ->
println(user.name)
}
Nesse caso em específico é Unit?
por conta da safe call que sempre retorna um nullable! Caso modificarmos a última instrução, teremos um nullable diferente:
val result: Long? = findUserById(1)?.let { user ->
println(user.name)
user.id
}
Portanto, se atente aos retornos do let
e de outras funções de escopo!
Função de escopo para configurar objetos durante a criação
Uma função de escopo bastante usada por conta do seu retorno, é a apply
. Um dos principais motivos é que ela sempre retorna o objeto do contexto.
Isso pode ser um pouco confuso, mas tem seus casos de uso. No artigo de datas do Jetpack Compose, eu fiz a implementação de um formatador de datas utilizando a apply
:
fun Long.toBrazilianDateFormat(
pattern: String = "dd/MM/yyyy"
): String {
val date = Date(this)
val formatter = SimpleDateFormat(
pattern, Locale("pt-br")
).apply {
timeZone = TimeZone.getTimeZone("GMT")
}
return formatter.format(date)
}
Veja que ao criar o SimpleDateFormat
, é feita uma configuração de TimeZone
e o retorno é o próprio formatador criado!
Em outras palavras, o apply
serve para aplicar configurações extras após criação de um objeto. Logo, a variável retornada será criada com as configurações esperadas!
Inclusive, essa mesma implementação poderia ser mais sucinta e sem nenhuma variável:
fun Long.toBrazilianDateFormat(
pattern: String = "dd/MM/yyyy"
): String = SimpleDateFormat(pattern, Locale("pt-br"))
.apply {
timeZone = TimeZone.getTimeZone("GMT")
}.format(Date(this))
Para saber mais
Esses são os casos mais comuns que utilizo funções de escopo no Kotlin, mas não para por aqui! Caso você quiser conhecer as demais funções como run
, also
, with
etc, recomendo que veja a documentação sobre funções de escopo.
Também, você pode aplicar outras técnicas, como chamadas encadeadas que permite usar mais de uma função de escopo em uma única chamada.
E ai, o que achou das funções de escopo do Kotlin? Você também usa no seu código? Aplica outras técnicas? Me conte aqui nos comentários 😄
Top comments (0)