src | theme | class | highlighter | mdc | drawings | image | selectable | colorSchema | title | author | export | |||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
./cover.md |
default |
text-center |
shiki |
true |
|
/side-logo.png |
true |
dark |
Kotlin |
Pablo Leon Rodrigues |
|
Kotlin é uma linguagem de programação multiplataforma, orientada a objetos e funcional, concisa e estaticamente tipada, desenvolvida pela JetBrains em 2011, que compila para a Máquina virtual Java e que também pode ser traduzida para a linguagem JavaScript e compilada para código nativo.
Uma das características mais importantes do Kotlin é a interoperabilidade fluida com Java. Como o código Kotlin é compilado até o bytecode da JVM, seu código Kotlin pode ser chamado diretamente no código Java e vice-versa. Isso significa que você pode aproveitar bibliotecas Java já existentes diretamente do Kotlin.
Além disso, a maioria das APIs do Android é gravada em Java, e você pode chamá-las diretamente do Kotlin.
::right::
fun main() {
println("Hello, world!")
}
::right::
fun
é usado para declarar funções
a função main()
é onde o programa inicia
o corpo da função é escrito entre chaves {}
println()
e print()
são usadas como saída padrão
;
não é necessário!
val customers = 10
println("We have $customers customers")
// We have 10 customers
println("We have ${customers + 1} customers")
// We have 11 customers
var customers = 10
customers = 8
customers = customers + 3 // addition: 11
customers += 7 // addition: 18
customers -= 3 // subtraction: 15
customers *= 2 // multiplication: 30
customers /= 3 // division: 10
println(customers) // 10
::right::
Categoria{style="color: green;"} | Tipos{style="color: green;"} |
---|---|
Integers | Byte , Short , Int , Long |
Unsigned integers | UByte , UShort , UInt , ULong |
Floating-point numbers | Float , Double |
Booleans | Boolean |
Characters | Char |
Strings | String |
No Kotlin, é possível ter um valor null
. A segurança nula detecta possíveis problemas com valores nulos em tempo de compilação, e não em tempo de execução.
A segurança nula é uma combinação de recursos que permitem:
- declare explicitamente quando valores nulos são permitidos em seu programa.
- verifique se há valores nulos.
- use chamadas seguras para propriedades ou funções que possam conter valores nulos.
- declare ações a serem executadas se valores nulos forem detectados.
::right::
fun main() {
// neverNull has String type
var neverNull: String = "can't be null"
// Throws a compiler error
neverNull = null
// nullable has nullable String type
var nullable: String? = "can be null here"
// This is OK
nullable = null
// null values aren't accepted
var inferredNonNull = "Compiler assumes non-nullable"
// Throws a compiler error
inferredNonNull = null
// notNull doesn't accept null values
fun strLength(notNull: String): Int {
return notNull.length
}
println(strLength(neverNull))// 18
println(strLength(nullable))// Throws compiler error
}
No exemplo a seguir, a função lengthString()
usa uma chamada segura para retornar o comprimento da string ou null
:
fun lengthString(maybeString: String?):
Int? = maybeString?.length
fun main() {
var nullString: String? = null
println(lengthString(nullString))
// null
}
fun main() {
var nullString: String? = null
println(nullString?.length ?: 0) // 0
}
::right::
Ao programar, é útil poder agrupar dados em estruturas para processamento posterior. O Kotlin fornece coleções exatamente para esse propósito.
As listas armazenam itens na ordem em que são adicionados e permitem itens duplicados. Para criar uma lista somente leitura (List), use a função listOf(). Para criar uma lista mutável (MutableList), use a função mutableListOf().
Ao criar listas, o Kotlin pode inferir o tipo de itens armazenados. Para declarar o tipo explicitamente, adicione o tipo entre colchetes angulares <> após a declaração da lista:
::right::
// Read only list
val readOnlyShapes =
listOf("triangle", "square", "circle")
println(readOnlyShapes)
// [triangle, square, circle]
// Mutable list, explicit type declaration
val shapes: MutableList<String> =
mutableListOf("triangle",
"square",
"circle")
println(shapes)
// [triangle, square, circle]
val readOnlyShapes = listOf("triangle", "square", "circle")
val shapes: MutableList<String> = mutableListOf("triangle", "square", "circle")
println("The first item in the list is: ${readOnlyShapes[0]}")
// The first item in the list is: triangle
println("The first item in the list is: ${readOnlyShapes.first()}")
// The first item in the list is: triangle
println("The first item in the list is: ${readOnlyShapes.last()}")
// The last item in the list is: circle
println("This list has ${readOnlyShapes.count()} items")
// This list has 3 items
println("circle" in readOnlyShapes)
// true
shapes.add("pentagon")
shapes.remove("pentagon")
Diferente das listas o Set
é um tipo de lista sem ordem e armazena itens únicos.
// Read-only set
val readOnlyFruit = setOf("apple", "banana", "cherry", "cherry")
// Mutable set with explicit type declaration
val fruit: MutableSet<String> = mutableSetOf("apple", "banana", "cherry", "cherry")
println(readOnlyFruit)
// [apple, banana, cherry]
As funções .count
, in
, .add
e .remove
de List estão disponíveis para Set.
Map é um tipo de estrutura que utiliza Key-value, chave e valor. Você pode acessar um valor de acordo com a sua chave. Cada chave em um mapa é única.
// Read-only map
val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println(readOnlyJuiceMenu)
// {apple=100, kiwi=190, orange=100}
// Mutable map with explicit type declaration
val juiceMenu: MutableMap<String, Int> =
mutableMapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println(juiceMenu)
// {apple=100, kiwi=190, orange=100}
println("The value of apple juice is: ${readOnlyJuiceMenu["apple"]}")
// The value of apple juice is: 100
println("This map has ${readOnlyJuiceMenu.count()} key-value pairs")
// This map has 3 key-value pairs
Para adicionar e remover a sintaxe é um pouco diferente:
val juiceMenu: MutableMap<String, Int> =
mutableMapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
juiceMenu.put("coconut", 150) // Add key "coconut" with value 150 to the map
println(juiceMenu)
// {apple=100, kiwi=190, orange=100, coconut=150}
juiceMenu.remove("orange") // Remove key "orange" from the map
println(juiceMenu)
// {apple=100, kiwi=190, coconut=150}
println(juiceMenu.containsKey("kiwi"))
// true
println(juiceMenu.keys)
// [apple, kiwi, orange]
println(juiceMenu.values)
// [100, 190, 100]
println("orange" in juiceMenu.keys)
// true
println(200 in juiceMenu.values)
// false
val d: Int
val check = true
if (check) {
d = 1
} else {
d = 2
}
println(d)
// 1
Não existe operador ternário no Kotlin, condition ? then : else
.
::right::
Aqui o When
é implementado como statement
val obj = "Hello"
when (obj) {
// Checks whether obj equals to "1"
"1" -> println("One")
// Checks whether obj equals "Hello"
"Hello" -> println("Greeting")
// Default statement
else -> println("Unknown")
}
// Greeting
Mas ele também pode ser implementado como expressão.
Aqui When
é utilizado como expressão que define o valor de uma variável.
val obj = "Hello"
val result = when (obj) {
"1" -> "One"
"Hello" -> "Greeting"
else -> "Unknown"
}
println(result)
// Greeting
::right::
val temp = 18
val description = when {
temp < 0 -> "very cold"
temp < 10 -> "a bit cold"
temp < 20 -> "warm"
else -> "hot"
}
println(description)
// warm
Em Kotlin podemos definir range
usando o operador ..
, o método mais comum de criar um range é 1..4
que é equivalente a 1,2,3,4
.
É possivel usar o operador <
para não incluir o último valor, 1..<4
, que representa 1,2,3
.
Para declarar o range
em ordem reversa podemos usar downTo
, 4 downTo 1
, resulta em 4,3,2,1
.
Para declarar um incremento maior que 1 podemos usar o step
, 1..5 step 2
, resulta em 1,3,5
.
Podemos usar também char
, 'a'..'d'
resulta em 'a','b','c','d'
.
::right::
for (number in 1..5) {
// number is the iterator
// and 1..5 is the range
print(number)
}
// 12345
val cakes =
listOf("carrot", "cheese", "chocolate")
for (cake in cakes) {
println("Yummy, it's a $cake cake!")
}
// Yummy, it's a carrot cake!
// Yummy, it's a cheese cake!
// Yummy, it's a chocolate cake!
While
pode ser usado de duas formas,
- Para executar um bloco de código enquanto uma expressão for verdadeira (
while
) - Para executar um bloco de código e depois verificar uma expressão condicional (
do-while
)
var cakesEaten = 0
while (cakesEaten < 3) {
println("Eat a cake")
cakesEaten++
}
// Eat a cake
// Eat a cake
// Eat a cake
::right::
var cakesEaten = 0
var cakesBaked = 0
while (cakesEaten < 3) {
println("Eat a cake")
cakesEaten++
}
do {
println("Bake a cake")
cakesBaked++
} while (cakesBaked < cakesEaten)
// Eat a cake
// Eat a cake
// Eat a cake
// Bake a cake
// Bake a cake
// Bake a cake
fun main() {
val name = "stranger" // Declare your first variable
println("Hi, $name!") // ...and use it!
print("Current count:")
for (i in 0..10) { // Loop over a range from 0 to 10
print(" $i")
}
}
Hi, stranger!
Current count: 0 1 2 3 4 5 6 7 8 9 10
val
é utilizado na declaração de constantes
var
é utilizado na declaração de variáveis
import kotlinx.coroutines.*
suspend fun main() { // A function that can be suspended and resumed later
val start = System.currentTimeMillis()
coroutineScope { // Create a scope for starting coroutines
for (i in 1..10) {
launch { // Start 10 concurrent tasks
delay(3000L - i * 300) // Pause their execution
log(start, "Countdown: $i")
}
}
}
// Execution continues when all coroutines in the scope have finished
log(start, "Liftoff!")
}
fun log(start: Long, msg: String) {
println("$msg " +
"(on ${Thread.currentThread().name}) " +
"after ${(System.currentTimeMillis() - start)/1000F}s")
}
abstract class Person(val name: String) {
abstract fun greet()
}
interface FoodConsumer {
fun eat()
fun pay(amount: Int) = println("Delicious! Here's $amount bucks!")
}
class RestaurantCustomer(name: String, val dish: String) : Person(name), FoodConsumer {
fun order() = println("$dish, please!")
override fun eat() = println("*Eats $dish*")
override fun greet() = println("It's me, $name.")
}
fun main() {
val sam = RestaurantCustomer("Sam", "Mixed salad")
sam.greet() // Implementation of abstract function
sam.order() // member function
sam.eat() // Implementation of interface function
sam.pay(10) // Default implementation in interface
}
import org.junit.Test // Tests
import kotlin.test.* // The following example works for JVM only
class SampleTest {
@Test
fun `test sum`() { // Write test names with whitespaces in backticks
val a = 1
val b = 41
assertEquals(42, sum(a, b), "Wrong result for sum($a, $b)")
}
@Test
fun `test computation`() {
assertTrue("Computation failed") {
setup() // Use lambda returning the test subject
compute()
}
}}
fun sum(a: Int, b: Int) = a + b // Sources
fun setup() {}
fun compute() = true