Aprendizado Kotlin - Alguns recursos da linguagem - Outras características (Null Safety) + Java e Kotlin no mesmo projeto

22 Apr 2020 » kotlin (aproximadamente 7 minutos de leitura)


Conheça a série sobre Kotlin

Introdução

Continuando aprendizado e descoberta sobre Kotlin. Falaremos sobre Outras características (Null Safety) + Java e Kotlin no mesmo projeto.

Recursos da linguagens observadores e experimentados

Nessa seção, pretendo falar de alguns recursos que pude experimentar durante o curso, e pratiquei em um projeto piloto que está disponível em um repositório no meu github onde pretendo colocar os demos do que ando testando com Kotlin. Esse repositório é o kotlin-lab.

Modificadores de visibilidade

Em Kotlin, classes, objetos, interfaces, construtores, funções e propriedades podem ser diferentes visibilidades. Elas existem em 4 níveis (ordenados aqui pelo nível de visibilidade): private < protected < internal < public. Se nenhum modificador é usado, por padrão é definido como public.

Funções, propriedades, classes podem ser declaradas em alto nível, diretamente em um pacote, como no exemplo abaixo:

// file name: example.kt
package foo

fun baz() { ... }
class Bar { ... }

Para esse contexto, os modificadores atendem o comportamento abaixo:

Protected = Não está disponível para declarações de alto-nível Private = Apenas no arquivo em questão. Internal = Dentro do mesmo módulo (conjunto de arquivos Kotlin compilados juntos. Dependência) Public = Menos restritivo modificador possível

Para classes e interfaces a estrutura segue a seguinte hierarquia:

Protected = Private+ visíveis em subclasses também Private = Apenas na classe em questão Internal = Dentro do mesmo módulo (conjunto de arquivos Kotlin compilados juntos. Dependência) Public = Menos restritivo modificador possível

Variáveis locais não tem recurso de modificadores de acesso e para construtores o único aplicado é o private.

Type aliases

É possível oferecer nomes alternativos para tipos existentes. Se o nome é muito longo e você quer colocar um nome mais curto ou mais lógico. Exemplos de uso:

typealias NodeSet = Set<Network.Node>

typealias FileTable<K> = MutableMap<K, MutableList<File>>

typealias MyHandler = (Int, String, Any) -> Unit

typealias Predicate<T> = (T) -> Boolean

class A {
inner class Inner
}
class B {
inner class Inner
}

typealias AInner = A.Inner
typealias BInner = B.Inner

Null Safety

Uma variável que não aponta para nenhum referência, aponta para null. Null não é um objeto. É como no Java, uma palavra reservada para fazer uma variável referenciar nenhum endereço de memória específico. Porém, em Java, existe uma exceção clássica chamada NullPointerException (NPE). Essa exceção é conhecida como o erro de um bilhão de dólares (referência). Esse erro é muito comum e normalmente causado por ausência de tratativa de possibilidades de atribuição de uma variável gerando impacto na execução do programa. Kotlin, encoraja você a não usar null, tanto quanto for possível. Uma variável por padrão não pode receber null, a não ser que ela explicitamente informe isso, através do sufico ?.

fun test(a: String, b: String?) {
}
test("a", "b") // execução ok
test("a", null) // execução ok
test(null, "b") //erro de compilação
test(null, null) //erro de compilação

Em Kotlin, é possível fazer chamadas seguras, através da sintaxe x?.y ou x?.y(). O que faz o compilador somente avançar na invocação, se e somente se, a variável x for != null.

Existe um outro recurso chamado, Elvis Operator, que tem a sintaxe x ?: y, onde, caso x, seja null, o valor de Y, é atribuído, que também é uma forma de tratar expressões com null em Kotlin.

Existe uma outra sintaxe, que caso, você coloque em uso, será levantada uma exceção NPE.

val x: String? = javaFunctionThatYouKnowReturnsNonNull()
val y: String = x!!//se X vier null, será levantada uma exceção.

O contexto acima citado, pode ser tratado de maneira elegante, especificando uma exceção do projeto, conforme sintaxe abaixo:

val y: String = x ?: throw SpecificException("Useful message")
y.importantFunction()

Em resumo, as únicas formas em Kotlin de existir um NPE são as seguintes:

  • Uma chamada explicita a NPE
  • Uso do operador !!
  • Inconsistência de dados na inicialização.
  • Interoperabilidade com o Java.

Cast e Type Casts

Em Kotlin, para verificar o tipo de um objeto existem os operadores is e !is. Eles seriam equivalente ao uso do operador instanceOf do Java.

Kotlin tem o recurso de Smart Cast para valores imutáveis.

O uso de smart casts não funciona quando o compilador não pode garantir que a variável não pode mudar entre a checagem e o uso.

Exemplo:

fun demo(x: Any) {
if (x is String) {
print(x.length) // x is automatically cast to String
}
}
if (x !is String) return

print(x.length) // x is automatically cast to String
// x is automatically cast to string on the right-hand side of `||`
if (x !is String || x.length == 0) return

// x is automatically cast to string on the right-hand side of `&&`
if (x is String && x.length > 0) {
print(x.length) // x is automatically cast to String
}
when (x) {
is Int -> print(x + 1)
is String -> print(x.length + 1)
is IntArray -> print(x.sum())
}

Interoperabilidade entre Java e Kotlin no mesmo projeto

É possível em um projeto Kotlin ter código Java e vice-versa. A IDE IntelliJ tem uma ferramenta que converte código Java em Kotlin.

public class Customer {

    private String name;

    public Customer(String s){
        name = s;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void placeOrder() {
        System.out.println("A new order is placed by " + name);
    }

}
val customer = Customer("Phase")
println(customer.name)
println(customer.placeOrder())

No link tem uns demos da IDE funcionando.

Conclusão

Nesse estudo, apresentei alguns recursos do Kotlin que são bastante inovadores para mim que vim da linguagem Java. Espero continuar aprendendo.


Conheça a série sobre Kotlin

Outras Fontes:

  • https://kotlinlang.org/docs/reference/properties.html
  • https://kotlinlang.org/docs/reference/visibility-modifiers.html
  • https://kotlinlang.org/docs/reference/type-aliases.html
  • https://kotlinlang.org/docs/tutorials/kotlin-for-py/null-safety.html
  • https://kotlinlang.org/docs/reference/null-safety.html#nullable-types-and-non-null-types
  • https://kotlinlang.org/docs/tutorials/mixing-java-kotlin-intellij.html
  • https://kotlinlang.org/docs/reference/java-interop.html
  • https://kotlinlang.org/docs/reference/java-to-kotlin-interop.html


Conheça a série sobre Kotlin