-
Properties in Kotlin classes can be declared either as mutable, using the
var
keyword, or as read-only, using theval
keyword.// full syntax for declaring a property var <propertyName>[: <PropertyType>] [= <property_initializer>] [<getter>] [<setter>] // example var stringRepresentation: String get() = this.toString() set(value) { setDataFromString(value) }
-
lateinit
modifier can be used on var properties when dependency injection, or in the setup method of a unit test. -
An interface with only one abstract method is called a functional interface, or a Single Abstract Method (SAM) interface.
fun interface IntPredicate { fun accept(i: Int): Boolean } // if don't use SAM interface, you will need to write code like this: // val isEven = object : IntPredicate { // override fun accept(i: Int): Boolean { // return i % 2 == 0 // } // } val isEven = IntPredicate { it % 2 == 0 } fun main() { println("Is 7 even? - ${isEven.accept(7)}") }
-
There are four visibility modifiers in Kotlin:
private
,protected
,internal
(visible in the same module), andpublic
. The default visibility ispublic
. -
Kotlin provides the ability to extend a class or an interface with new functionality without having to inherit from the class or use design patterns such as Decorator. This is done via special declarations called extensions.
fun MutableList<Int>.swap(index1: Int, index2: Int) { val tmp = this[index1] // 'this' corresponds to the list this[index1] = this[index2] this[index2] = tmp } val list = mutableListOf(1, 2, 3) list.swap(0, 2) // 'this' inside 'swap()' will hold the value of 'list'
If a class has a member function, and an extension function is defined which has the same receiver type, the same name, and is applicable to given arguments, the member always wins.
Kotlin supports extension properties much like it supports functions:
val <T> List<T>.lastIndex: Int get() = size - 1
By the way, it's better to define extensions on the top level, directly under packages
-
Data classes in Kotlin are classes whose main purpose is to hold data. The compiler automatically derives the following members from all properties declared in the primary constructor
data class User(val name: String, val age: Int)
Component functions generated for data classes make it possible to use them in destructuring declarations:
val jane = User("Jane", 35) val (name, age) = jane println("$name, $age years of age") // Jane, 35 years of age