In this article I will describe the main innovations in the syntax compared to previous versions.
The full list of new features can be found here:
https://kotlinlang.org/docs/whatsnew20.html
Context Receivers:
// Kotlin 1.x:
class User(
val name: String
)
fun greet(user: User) {
with(user) {
println("Hello, $name")
}
}
fun main() {
greet(User("Alice"))
}
// Kotlin 2.0:
// Now you can add contexts for functions,
// to explicitly specify their dependencies at the API level:
class User(
val name: String
)
context(User)
fun greet() {
println("Hello, $name")
}
fun main() {
val user = User("Alice")
with(user) {
greet()
}
}Value classes (renamed inline classes):
They work similarly, but the new name better reflects their essence, and also provides additional optimizations when using such classes on the JVM.
// Kotlin 1.x: inline class Name( val value: String ) // Kotlin 2.0: @JvmInline value class Name( val value: String )
Sealed Interface:
// Kotlin 1.x:
sealed class Shape {
class Circle(
val radius: Double
) : Shape()
class Square(
val side: Double
) : Shape()
}
// Kotlin 2.0:
// now you can make sealed interfaces
sealed interface Shape
class Circle(
val radius: Double
) : Shape
class Square(
val side: Double
) : ShapeLabels for lambdas and anonymous functions:
fun process(
action: () -> Unit
) {
action()
}
fun main() {
process {
return@process println("Lambda with label")
}
}Support for new collection operations:
val list = listOf(1, 2, 3)
val doubled = list.mapNotNull {
if (it > 1) it * 2
else null
}Support for new syntax for pattern matching in when:
sealed class Shape
class Circle(
val radius: Double
) : Shape()
class Square(
val side: Double
) : Shape()
fun describeShape(shape: Shape): String = when (shape) {
is Circle -> "Circle with radius ${shape.radius}"
is Square -> "Square with side ${shape.side}"
}Multi-declarations for classes with operator:
data class Person(
val name: String,
val age: Int
)
fun main() {
val (name, age) = Person("Alice", 30)
println("Name: $name, Age: $age")
}For loops and destructuring improvements:
For loops can now destructure objects directly within the loop body
data class Person(
val name: String,
val age: Int
)
fun main() {
val people = listOf(
Person("Alice", 30),
Person("Bob", 25)
)
for ((name, age) in people) {
println("$name is $age years old")
}
}Support for improved operators for generics and generic types:
class Container<T>(val value: T) {
operator fun plus(other: Container<T>): Container<T> {
return Container(other.value)
}
}
fun main() {
val container1 = Container(10)
val container2 = Container(20)
println(container1 + container2)
}