immediate assignment val b = 2 // `Int` type is inferred val c: Int // Type required when no initializer is provided c = 3 // deferred assignment // .. . }
0 val s: String = "Hello" val PI = 3.14 var x = 0 val s = "Hello" Double PI = 3.14; Integer x = 0; String s = "Hello"; Explicit types Type inference final var PI = 3.14; var x = 0; final var s = "Hello"; Type inference (local variables) Explicit types
x: Int, y: Int - > x + y } val sum = { x: Int, y: Int -> x + y } typealias IntAdder = (Int, Int) -> Int val sum: IntAdder = { x: Int, y: Int -> x + y }
= 1, val depth: Int = 1, color: Color = Color.BLACK, description: String = "This is a 3d figure", ) Default values + named arguments Figure(Color.RED, "Red figure")
= 1, val depth: Int = 1, color: Color = Color.BLACK, description: String = "This is a 3d figure", ) Default values + named arguments Figure(color = Color.RED, description = "Red figure")
or an extension function with a specific name for the corresponding type. data class Point(val x: Int, val y: Int) operator fun Point.unaryMinus() = Point(-x, -y) val point = Point(10, 20) fun main() { println(-point) // prints "Point(x=-10, y=-20)" }
(weather is Rainy) { result = Safe } else { result = Calm } return result } fun adjustSpeed(weather: Weather) = if (weather is Rainy) Safe else Calm Note to myself: show in the IDE
-> Safe // else -> Calm } Compilation error: We should either specify all options or use the ‘else’ branch sealed class Weather object Rainy : Weather() object Sunny : Weather()
0 .. args.size - 1) { println("$i: ${args[i]}") } } for (i in 0 until args.size) { println("$i: ${args[i]}") } for (i in args.indices) { println("$i: ${args[i]}") }
0 .. args.size - 1) { println("$i: ${args[i]}") } } for (i in 0 until args.size) { println("$i: ${args[i]}") } for (i in args.indices) { println("$i: ${args[i]}") } for ((i, value) in args.withIndex()) { println("$i: $value}") }
status: Status) fun function( ... ): Result { // computations return Result(result, status) } // Now, to use this function: val (result, status) = function( .. . )
order ! ! .customer ! ! .address ! ! .city “You may notice that the double exclamation mark looks a bit rude: it’s almost like you’re yelling at the compiler. This is intentional.” - Kotlin in Action
data: String) private var state: State? = null @BeforeEach fun setup() { state = State("abc") } @Test fun foo() { assertEquals("abc", state ! ! .data) } } class MyTest { class State(val data: String) private lateinit var state: State @BeforeEach fun setup() { state = State("abc") } @Test fun foo() { assertEquals("abc", state.data) } }
String?, val age: Int?) fun processPerson(person: Person) { val name = person.name if (name = = null) throw IllegalArgumentException("Named required") val age = person.age if (age == null) return println("$name: $age") }
String?, val age: Int?) fun processPerson(person: Person) { val name = person.name if (name = = null) throw IllegalArgumentException("Named required") val age = person.age if (age == null) return println("$name: $age") }
String?, val age: Int?) fun processPerson(person: Person) { val name = person.name if (name = = null) throw IllegalArgumentException("Named required") val age = person.age if (age == null) return println("$name: $age") }
String?, val age: Int?) fun processPerson(person: Person) { val name = person.name ? : throw IllegalArgumentException("Named required") val age = person.age ?: return println("$name: $age") }
Any?) : Boolean { val command = other as Command return command.id == id } override fun equals(other: Any?) : Boolean { return (other as? Command) ?. id == id } ‘as’ throws a ClassCastException on cast failure ‘as?’ returns null value on cast failure