A brief tour of some of the more outstanding features of Kotlin, highlighting the caveats of certain features and flaws that will have you scratching your head for hours.
2. Who?
• Programming for a living since 1994
• Doing Java since 2000
• Experience in Java, C, C#, Objective-C,
Groovy, Scala
• Worked on Ceylon compiler 2012-2017
• Became Java Champion in 2015
#Hashtag
@chochosmx
3. Kotlin
• Created by JetBrains
• Static typing
• Not Java!
• Official Android support
• JVM, Javascript
#Hashtag
@twitter
4. Nice features
• Data classes
• Destructuring
• Lambdas, higher order functions, function refs, method
refs
• Top-level methods
• Declaration-site variance
• Type inference
• "Typesafe null"
• String interpolation
#Hashtag
@twitter
5. THE GOOD PARTS: DATA CLASSES
data class Person(val name:String,
val birthDate:Date)
•toString() and equals() automagically added
•no hashCode() though
6. THE GOOD PARTS: DESTRUCTURING
val p = Person("John Doe", today)
val (n, f) = p
val map = mapOf(1 to "one",
2 to "two")
for ((k, v) in map) {
...
}
7. THE GOOD PARTS: FUNCTIONS
fun foo() { ... }
fun bar(f:() -> (Unit)) = f()
bar(::foo)
bar( { println("baz") } )
8. THE GOOD PARTS: STRING INTERPOLATION
val p = Person("John Doe", today)
val (n, f) = p
println("Name: $n birth: ${p.birthDate}")
9. THE GOOD PARTS: TYPE INFERENCE
val p = "hello"
fun foo(bar:String) = bar.length
fun foo(bar:String) {
return bar.length
}
10. THE GOOD PARTS: SMART CASTS
val p:Any = "string"
if (p is String) {
println(p.toUpperCase())
}
11. NOT SO GOOD: STILL HAVE CASTS
val p:Any = 1
if (p is Int) {
println((p as String).toUpperCase())
}
12. THE GOOD PARTS: TYPESAFE NULL
var p = "hello"
p = null
var p:String? = "hello"
p = null
🚫
13. THE GOOD PARTS: TYPESAFE NULL
var x:String? = "hello"
fun foo(s:String) {...}
foo(x) //COMPILER ERROR
if (x != null) {
foo(x)
}
14. NOT GOOD: TYPESAFE NULL KILLSWITCH
var x:String? = "hello"
fun foo(s:String) {...}
foo(x!!) //RUNTIME ERROR
15. NOT GOOD: TYPESAFE NULL KILLSWITCH
fun foo(s:String?) {
println(s?.length)
}
foo(x?:"")
fun bar(s:String?) {
println(s!!.length)
}
foo(x!!)
✔
✘
16. GOOD: OPERATOR OVERLOADING
class Foo(val x:Int) {
operator fun plus(o:Foo) =
Foo(o.x + x)
operator fun times(o:Foo) =
Foo(o.x * x)
}
17. GOOD: OPERATOR OVERLOADING
val a = Foo(1)
val b = Foo(2)
println(a + b)
println(a * b)
println(a.plus(b))
println(a.times(b))
18. NOT SO GOOD: INFORMAL OPERATOR OVERLOADING
➤ No interfaces to define behavior
➤ Could have used static typing here
class Foo(val x:Int) {
operator fun plus(o:Foo) =
Foo(x+o.x)
fun plus(i:Int) = x+i
}
println(Foo(1)+1)
19. GOOD: EXTENSION METHODS
data class Person(val name:String,
val birthDate:Date)
fun Person.debug() {
println("I'm $name born on $birthDate")
}
20. NOT SO GOOD: EXTENSION OPERATORS
data class Person(val name:String,
val birthDate:Date)
operator fun Person.plus(other:Person) {
????
}
21. REALLY NOT GOOD: NONLOCAL RETURN
fun foo() {
listOf(1, 2, 3).forEach {
println(it)
if (it > 0) {
return
}
}
println("All done!")
}