๐ Advanced and other Kotlin features
Delegated properties
Kotlin allows to delegate the getter and setter of a property to another object, which is called a delegate. It is a class that defines the getValue
and setValue
methods.
Kotlin provides standard delegates such lazy properties and observable properties.
โถ๏ธ this code illustrates delegate properties.
Concurrency and Coroutines
Kotlin provides a high level concurrency model called Coroutines. The developer can delegated the management of threads to the compiler and runtime and using higher level constructs than threads to express asynchronous operations.
Coroutines in Kotlin revolve around these concepts:
- A coroutine is an instance of suspendable computation.
- Kotlin has many methods for creating a coroutine such as
launch
.
- Kotlin has many methods for creating a coroutine such as
- A coroutine must exist within a coroutine scope.
- For example
runBlocking
creates a coroutine scope whithin which coroutines can be launched.
- For example
- A coroutine can run suspend functions which can suspend the coroutine but do not block the thread.
- For example: the
delay
suspend the coroutine but does not block the thread on which it is running. - Suspend functions are operations that may take time such http requests and file system calls.
- For example: the
- The
suspend
qualifier defines a suspend function. It runs within a coroutine and can call other suspend functions. Flow
allows to generate a list of asynchronous values.Deferred
andChannel
transfer a single value and a stream of values, respectively, between coroutines.
โถ๏ธ this code show how to create a coroutine and suspend function and how to use them.
โถ๏ธ this code illustrated flows.
โถ๏ธ this code illustrates channels and deferred.
Function literal with receiver and Type-safe builders
As seen previously, function extension add behavior to existing classes. Inside the definition of the function extension, we can reference the extension receiver (or this) implicitly.
fun String.countCharacters() = length // or this.length
println("hello".countCharacters()) // prints 5
We can define this extension with a function literal (or lambda) in instead of a named function (declared with fun
).
var extFn: String.() -> Int
extFn = { length } // extFn is a function literal
println("hello".extFn()) // prints 5
println(extFn("hello")) // prints 5
extFn
is a function literal (lambda) that has access to the receiver (this). That's why it's called a function literal with receiver.
extFn("hello")
or extFn("hello")
call the extension as expected from extension functions.
The type of a function literal with receiver is funName: ReceiverType.(arg1Type, arg2Type, etc.) -> ReturnType
and is called with funName(receiverValue, arg1Value, etc.)
or receiverValue.funName(arg1Value, etc.)
. However, this is not the interesting aspect.
The important part is extFn = { length }
which can be put as a function argument in a higher order function. The developer that calls the higher order function must define extFn
, which in turn has access to the receiver. This allows for a nice style of programming. โถ๏ธ this code shows an example.
Type-safe builders combine well-named builder functions and functions literals with receiver to create type-safe, statically typed builders in Kotlin.
Builder pattern
The builder pattern is a way to construct complex objects.
// StirngBuilder uses the builder pattern
val text = StringBuilder("Temp")
.append(1)
.append(true)
.append("friend")
.toString()
This code shows a basic type-safe builder.
Kotlin docs provides an example of an advanced type-safe builder that builds an HTML page.
๐งช Exercises
Exercise 1
- open the java-integration-exercise projects in the materials folder.
- Have a look at the Java class we provided you in the
src/main/java/com/worldline/learning/kotlin/java2kotlin
package. (yes, that's the Pokemon class) - Convert that Java class in Kotlin using IntelliJ's awesome copy-pasta tool! (just copy paste the java code in a kotlin file, one is provided at
src/main/kotlin/com/worldline/learning/kotlin/java2kotlin
) - Have a look at the generated Kotlin code, and note the major differences you spot!