Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Bulletproofing your foot for Kotlin

Bulletproofing your foot for Kotlin

Kotlin is the hot new language for the JVM, and a shiny new toy for many developers. Come and learn what it has to offer, its benefits and advantages over Java, and how to avoid shooting yourself in the foot when you start using it.

Enrique Zamudio

February 23, 2018
Tweet

More Decks by Enrique Zamudio

Other Decks in Technology

Transcript

  1. 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 @chochosmx
  2. KOTLIN ➤ Created by JetBrains ➤ Static typing ➤ Not

    Java! ➤ Official Android support ➤ JVM, Javascript @twitter
  3. 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 @twitter
  4. THE GOOD PARTS: DATA CLASSES data class Person(val name:String, val

    birthDate:Date) •toString() and equals() automagically added •no hashCode() though
  5. 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) { ... }
  6. THE GOOD PARTS: FUNCTIONS fun foo() { ... } fun

    bar(f:() -> (Unit)) = f() bar(::foo) bar( { println("baz") } )
  7. THE GOOD PARTS: STRING INTERPOLATION val p = Person("John Doe",

    today) val (n, f) = p println("Name: $n birth: ${p.birthDate}")
  8. THE GOOD PARTS: TYPE INFERENCE val p = "hello" fun

    foo(bar:String) = bar.length fun bar(baz:String) { return baz.length }
  9. THE GOOD PARTS: SMART CASTS val p:Any = "string" if

    (p is String) { println(p.toUpperCase()) }
  10. NOT SO GOOD: STILL HAVE CASTS val p:Any = 1

    if (p is Int) { println((p as String).toUpperCase()) }
  11. THE GOOD PARTS: TYPESAFE NULL var p = "hello" p

    = null var p:String? = "hello" p = null
  12. THE GOOD PARTS: TYPESAFE NULL var x:String? = "hello" fun

    foo(s:String) {...} foo(x) //COMPILER ERROR if (x != null) { foo(x) }
  13. NOT GOOD: TYPESAFE NULL KILLSWITCH var x:String? = "hello" fun

    foo(s:String) {...} foo(x!!) //RUNTIME ERROR
  14. NOT GOOD: TYPESAFE NULL KILLSWITCH fun foo(s:String?) { println(s?.length) }

    foo(x?:"") fun bar(s:String?) { println(s!!.length) } foo(x!!) ✔ ✘
  15. 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) }
  16. 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))
  17. 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)
  18. GOOD: EXTENSION METHODS data class Person(val name:String, val birthDate:Date) fun

    Person.debug() { println("I'm $name born on $birthDate") }
  19. NOT SO GOOD: EXTENSION OPERATORS data class Person(val name:String, val

    birthDate:Date) operator fun Person.plus(other:Person) { return Person(name+other.name, ... }
  20. REALLY NOT GOOD: NONLOCAL RETURN fun foo() { listOf(1, 2,

    3).forEach { println(it) if (it > 0) { return } println("WAT") } println("All done!") }
  21. REALLY NOT GOOD: NONLOCAL RETURN fun foo() { listOf(1, 2,

    3).forEach { println(it) if (it > 0) { return@forEach } println("WAT") } println("All done!") }