in Java) • No guarantee about immutability • Immutability -> thread safety • Even you are using var, try to think about why • Try to get rid / isolate state
everything is open by default, unless you add the keyword final • In Kotlin everything is closed by default, unless you add the keyword open • Prefer composition when it's possible • A data class cannot be open • Inheritance breaks equality
Base(val name: String) data class Derived(name: String, val secondName: String): Base(name) val base = Base("base") val derived = Derived("base", "other") base == derived // true derived == base // false
in my method / constructor // Kotlin class Person(val fullName: String, val nickName: String? = null) // Java class Person person = new Person("Lorenzo"); // error
// Kotlin class Person @JvmOverloads constructor( val fullName: String, val nickName: String? = null ) // Java class Person person = new Person("Lorenzo"); // OK!
with Java code as it does with Kotlin code // accessing through person.getName() val name = person.name // accessing through person.setName(String newName) person.name = "Mario"
to create implementations of Java interfaces with a single non-default method public interface Action { void run(); } val action = Action { println("Yay!") }
// This is fine val nullableString: String? = something.getString() // Type mismatch: required String found String? val notnullString: String = something.getString() The compiler is now able to help us
be declared both as top level functions or inside a class • They don't really modify the receiver class • They are compiled as static functions only if they are top level and so they are also dispatched statically!
fun Base.shout() = println("I'm base!") fun Derived.shout() = println("I'm derived!") val first = Derived() val second: Base = Derived() first.shout() second.shout()
fun Base.shout() = println("I'm base!") fun Derived.shout() = println("I'm derived!") val first = Derived() val second: Base = Derived() first.shout() // "I'm derived!" second.shout() // "I'm base!"
to understand what's optional and what's not • When something is optional, try to understand what's going to happen when it's absent (is there a default? Or just don't show that piece of information?)
build cache since Kotlin 1.2.20 (add org.gradle.caching=true in your gradle.properties) • Avoid recompilation of Kotlin file adding kotlin.incremental.usePreciseJavaTracking=true to your gradle.properties (experimental!) • Gradle 4.7 supports incremental annotation