Kittinun Vantasin
2010 Started
2011 Revealed
Late 2012 OSS
2014
Gain popularity
2016
Hit 1.0
2017
Hit 1.1
Late 2017
Hit 1.2
2018
Hit 1.3
Kotlin 1.2.71 or earlier
Awesome Kotlin 1.3
fun foo(s: String?) {
s?.let {
s.length // smart cast is here
}
if (s.isNotNull()) {
s?.length // no smart cast here :(
}
}
fun String?.isNotNull() = this != null
fun foo(s: String?) {
s?.let {
s.length // smart cast here
}
if (isNotNull(s)) {
s.length // also smart cast here
}
}
fun isNotNull(value: Any?): Boolean {
contract { returns(true) implies (value != null) }
return value != null
}
val myValue: String
myRun {
myValue = "Hello, World!" // Error here ... :(
}
fun <R> myRun(block: () -> R): R {
return block()
}
val myValue: String
myRun {
myValue = "Hello, World!" // Woohoo it works!
}
fun <R> myRun(block: () -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
val answer = calculate()
return when(answer) {
42 -> "Right answer!"
123 -> "ARGHHHHH!"
else -> "Sorry, $answer is not correct"
}
answer // I don't want to see you here
return when(val answer = calculate()) {
42 -> "Right answer!"
123 -> "ARGHHHHH!"
else -> "Sorry, $answer is not correct"
}
//answer you are not being seen here
interface Foo {
companion object {
@JvmField
val bar: Int = 42
@JvmStatic
fun sayHello(name: String = "") {
println("Hello, $name")
}
}
}
fun main() {
println("Hello, world")
}
// compare to the full-blown version
fun main(args : Array<String>) {
println("Hello, world")
}
fun onlyRealManCanUnderstandThis(
block: (Any, Any, Any, /* 250 more */, Any, Any
) {
block(Any(), Any(), /* 250 more */, Any(), Any())
}
@SinceKotlin("1.3")
interface FunctionN<out R> : Function<R> {
operator fun invoke(vararg args: Any?): R
override val arity: Int
}
class FirstNameInKana(n: String)
class LastNameInKana(n: String)
fun formattedName(f: FirstName, l: LastName) {
println("$l $f")
}
formattedName(
FirstNameInKana("やまだ"),
LastNameInKana("たろう")
)
typealias FirstName = String // OK, but meh :|
typealias LastName = String // OK, but meh :|
inline class FirstNameInKana(n: String)
inline class LastNameInKana(n: String)
fun formattedName(f: FirstName, l: LastName) {
println("$l $f")
}
formattedName(
FirstNameInKana("やまだ"),
LastNameInKana("たろう")
)
Must have a public constructor with a single val
No init block
Must be final
Cannot extend anything - implement interfaces OK
Cannot have any additional properties
Must be a top level class
// Literal shortcode for UInt
val aUInt: UInt = 3u
val aULong: ULong = 3uL
// And from Hex...
val hexUByte: UByte = 0xFFu // 255
val hexUShort: UShort = 0xFFFFu // 65535
val hexUInt: UInt = 0xFFFF_FFFFu // 4294967295
val hexULong: ULong = 0xFFFF_FFFF_FFFF_FFFFu // xD
fun calculateArray(): Array<Int>? {
// some calculation
}
val array = calculateArray()
array.isNullOrEmpty() // ERRRAARGGHHH, there is none
fun calculateArray(): Array<Int>? {
// heavy calculation
}
val array = calculateArray()
if (array.isNullOrEmpty()) {
// :) Joy
}
val maybeArray: Array<T>
maybeArray.isNullOrEmpty()
val maybeCollection: Collection<T>
maybeCollection.isNullOrEmpty()
val maybeMap: Map<T, U>
maybeMap.isNullOrEmpty()
val listOfFeatures: List<String> = ...
println(listOfFeatures.ifEmpty {
listOf("Default1", "Default2")
})
val townProvidedByUser: String = ...
println(townProvidedByUser.ifBlank { "東京" })
@Serializable
data class Destination(
val name: String? = "",
val country : String? = "",
val code : Int = 0,
@Optional
val isMetro : Boolean = false,
@Transient
val favorite : Boolean = false
)
val tokyoAsString = JSON.stringify(
Destination(name = "東京", country = "Japan")
) // { "name":"東京","country":"Japan","code":0 }
val tokyo = JSON.unquoted.parse<Destination>(
"{ name:東京,country:Japan, code:12 }"
) // Destination(name = "東京", country = "Japan", code = 12)
The experimental feature is really experimenting!
They can be breaking for the next version! :)