$30 off During Our Annual Pro Sale. View Details »

You can do better with Kotlin

You can do better with Kotlin

Introduction to Kotlin talk.

Svetlana Isakova

March 03, 2016
Tweet

More Decks by Svetlana Isakova

Other Decks in Programming

Transcript

  1. Svetlana Isakova
    You can do better with Kotlin

    View Slide

  2. - modern
    - pragmatic
    - Android-friendly
    Kotlin Programming
    Language

    View Slide

  3. Official on Android

    View Slide

  4. Not only Android

    View Slide

  5. Multiplatform projects

    View Slide

  6. Pragmatic
    - tooling
    - Java interop

    View Slide

  7. From

    View Slide

  8. has good tooling

    View Slide

  9. - completion
    - navigation
    - refactorings
    - inspections

    View Slide

  10. can be easily mixed
    with Java code

    View Slide

  11. *.java
    *.class
    *.dex
    compiled to Java bytecode
    *.kt

    View Slide

  12. Kotlin code
    Java code
    You can have Java &
    Kotlin code in one project

    View Slide

  13. You can gradually add
    Kotlin to your existing app

    View Slide

  14. Android-friendly

    View Slide

  15. Android Studio
    is based on
    IntelliJ IDEA

    View Slide

  16. just another library
    for your app
    rxjava-2.1.2
    kotlin-stdlib-1.1.4 6315
    10212

    View Slide

  17. No Kotlin SDK
    …just JDK + extensions
    small runtime jar easy Java interop

    View Slide

  18. Modern
    - concise
    - safe
    - expressive

    View Slide

  19. concise

    View Slide

  20. public class Person {

    private final String name;

    private final int age;


    public Person(String name, int age) {

    this.name = name;

    this.age = age;

    }


    public String getName() {

    return name;

    }


    public int getAge() {

    return age;

    }

    }

    View Slide

  21. - equals
    - hashCode
    - toString

    data 

    class Person(val name: String, val age: Int)

    View Slide

  22. public class Person {

    private final String name;

    private final int age;


    public Person(String name, int age) {

    this.name = name;

    this.age = age;

    }


    public String getName() {

    return name;

    }


    public int getAge() {

    return age;

    }

    }

    class Person(
    val name: String,
    val age: Int
    )
    person.name
    person.getName()

    View Slide


  23. class Person(
    val name: String,
    val age: Int
    )
    person.getName()

    View Slide

  24. public class Person {

    private final String name;

    private final int age;


    public Person(String name, int age) {

    this.name = name;

    this.age = age;

    }


    public String getName() {

    return name;

    }


    public int getAge() {

    return age;

    }

    }
    person.name

    View Slide

  25. public void updateWeather(int degrees) {

    String description;

    Colour colour;

    if (degrees < 5) {

    description = "cold";

    colour = BLUE;

    } else if (degrees < 23) {

    description = "mild";

    colour = ORANGE;

    } else {

    description = "hot";

    colour = RED;

    }

    // ...

    }
    enum Colour { BLUE, ORANGE, RED, /*...*/; }

    View Slide

  26. fun updateWeather(degrees: Int) {

    val description: String

    val colour: Colour

    if (degrees < 5) {

    description = "cold"

    colour = BLUE

    } else if (degrees < 23) {

    description = "mild"

    colour = ORANGE

    } else {

    description = "hot"

    colour = RED

    }

    // ...

    }

    View Slide

  27. fun updateWeather(degrees: Int) {

    val (description: String, colour: Colour) =

    if (degrees < 5) {

    Pair("cold", BLUE)

    } else if (degrees < 23) {

    Pair("mild", ORANGE)

    } else {

    Pair("hot", RED)

    }
    // ...

    }

    View Slide

  28. fun updateWeather(degrees: Int) {

    val (description, colour) =

    if (degrees < 5) {

    Pair("cold", BLUE)

    } else if (degrees < 23) {

    Pair("mild", ORANGE)

    } else {

    Pair("hot", RED)

    }
    // ...

    }

    View Slide

  29. fun updateWeather(degrees: Int) {

    val (description, colour) = when {

    degrees < 5 -> Pair("cold", BLUE)

    degrees < 23 -> Pair("mild", ORANGE)

    else -> Pair("hot", RED)

    }
    // ...

    }

    View Slide

  30. fun updateWeather(degrees: Int) {

    val (description, colour) = when {

    degrees < 5 -> "cold" to BLUE

    degrees < 23 -> "mild" to ORANGE

    else -> "hot" to RED

    }

    }

    View Slide

  31. val (description, colour) = when {

    degrees < 5 -> "cold" to BLUE

    degrees < 23 -> "mild" to ORANGE

    else -> "hot" to RED

    }
    String description;

    Colour colour;
    if (degrees < 5) {

    description = "cold";

    colour = BLUE;

    } else if (degrees < 23) {

    description = "mild";

    colour = ORANGE;

    } else {

    description = "hot";

    colour = RED;

    }

    View Slide

  32. safe

    View Slide

  33. Billion Dollar Mistake

    View Slide

  34. Modern approach:
    to make NPE
    compile-time error,
    not run-time error

    View Slide

  35. Nullable types in Kotlin
    val s1: String = "always not null"

    val s2: String? = null
    s1.length ✓

    s2.length
    "can be null or non-null"
    null ✗

    View Slide

  36. val s: String?
    if (s != null) {

    s.length

    }
    Dealing with Nullable Types

    View Slide

  37. s?.length
    val s: String?
    Dealing with Nullable Types

    View Slide

  38. val length = if (s != null) s.length else null
    val s: String?
    Nullability operators
    val length = s?.length

    View Slide

  39. val length = if (s != null) s.length else null
    val s: String?
    Nullability operators
    val length: Int? = s?.length

    View Slide

  40. val length = if (s != null) s.length else 0
    val s: String?
    Nullability operators
    val length: Int = s?.length ?: 0

    View Slide

  41. val s: String?
    if (s == null) fail()

    s.length
    Control-flow analysis

    View Slide

  42. val s: String?
    Making NPE explicit
    s!!
    throws NPE if s is null
    s!!.length

    View Slide

  43. Nullable Types Under the Hood
    No performance overhead
    @Nullable, @NotNull annotations

    View Slide

  44. Annotate your Java types in Kotlin
    Type
    behaves like
    regular Java type
    @Nullable
    @NotNull Type
    Type?
    Type
    Type
    @ParametersAreNonnullByDefault
    @MyNonnullApi
    Type/Type?

    View Slide

  45. class Optional(val value: T) {

    fun isPresent() = value != null


    fun get() = value ?:

    throw NoSuchElementException("No value present")
    }
    Nullable types ≠ Optional

    View Slide

  46. expressive

    View Slide

  47. you can avoid any repetition
    you can make the code look nicer
    you can create API looking like DSL
    expressive

    View Slide

  48. Extension Functions

    View Slide

  49. fun String.lastChar() = get(length - 1)
    this can be omitted
    Extension Functions
    fun String.lastChar() = this.get(this.length - 1)

    View Slide

  50. import com.example.util.lastChar
    import com.example.util.*
    Extension Functions
    val c: Char = "abc".lastChar()
    fun String.lastChar() = get(length - 1)

    View Slide

  51. fun String.lastChar() = get(length - 1)
    Calling Extension Functions
    from Java code
    StringExtensions.kt
    char c = StringExtensionsKt.lastChar("abc");
    JavaClass.java
    import static StringExtensionsKt.lastChar;
    char c = lastChar("abc");

    View Slide

  52. No. Because it’s a regular
    static method under the hood.
    fun String.lastChar() = get(length - 1)
    Extension Functions
    Is it possible to call a private
    member of String here?

    View Slide

  53. Extensions for Android
    Toast.makeText(this, "Thank you!”, Toast.LENGTH_SHORT).show()
    Activity
    extension function
    on Activity
    toast("Thank you!")
    this.toast("Thank you!")

    View Slide

  54. this.startActivity(“ANSWER" to 42)
    val intent = Intent(this, NewActivity::class.java)

    intent.putExtra("ANSWER", 42)

    startActivity(intent)
    Extensions for Android

    View Slide

  55. infix fun A.to(that: B) = Pair(this, that)
    "ANSWER".to(42)
    "hot" to RED
    mapOf(0 to "zero", 1 to "one")
    The to extension function

    View Slide

  56. Lambdas

    View Slide

  57. Lambdas
    button.addActionListener { println("Hi") }

    View Slide

  58. { employee: Employee -> employee.city == City.PRAGUE }
    What’s an average
    age of employees
    working in Prague?
    Working with collections with Lambdas
    val employees: List
    employees.filter { it.city == City.PRAGUE }.map { it.age }.average()
    data class Employee(
    val city: City, val age: Int
    )

    View Slide

  59. What’s an average
    age of employees
    working in Prague?
    Working with collections with Lambdas
    val employees: List
    data class Employee(
    val city: City, val age: Int
    )
    extension functions
    employees.filter { it.city == City.PRAGUE }.map { it.age }.average()

    View Slide

  60. Kotlin library: extensions on collections
    • filter
    • map
    • reduce
    • count
    • find
    • any
    • flatMap
    • groupBy
    • …

    View Slide

  61. Under the Hood
    No performance overhead
    Lambdas can be inlined

    View Slide

  62. Extension Function & Lambda
    Lambda with receiver

    View Slide

  63. val sb = StringBuilder()

    with (sb) {

    appendln("Alphabet: ")

    for (c in 'a'..'z') {

    append(c)

    }
    toString()

    }
    The with function
    with is a function
    val sb = StringBuilder()

    sb.appendln("Alphabet: ")

    for (c in 'a'..'z') {

    sb.append(c)

    }

    sb.toString()


    View Slide

  64. lambda
    is its
    second
    argument
    val sb = StringBuilder()

    with (sb) {

    this.appendln(“Alphabet: ")

    for (c in 'a'..'z') {

    this.append(c)

    }
    this.toString()

    }
    val sb = StringBuilder()

    with (sb, { ->

    this.appendln(“Alphabet: ")

    for (c in 'a'..'z') {

    this.append(c)

    }
    this.toString()

    })
    lambda
    is its
    second
    argument
    Lambda with receiver
    with is a function
    this is
    an implicit receiver
    in the lambda
    val sb = StringBuilder()

    with (sb) {

    appendln("Alphabet: ")

    for (c in 'a'..'z') {

    append(c)

    }
    toString()

    }
    this can be omitted

    View Slide

  65. with (sb) {

    appendln("Alphabet: ")

    ...

    }
    inline fun with(
    receiver: T,
    block: T.() -> R
    ): R = receiver.block()
    The with function declaration

    View Slide

  66. Lambda with receiver
    val sb = StringBuilder()

    with (sb) {

    appendln("Alphabet: ")

    for (c in 'a'..'z') {

    this.append(c)

    }

    }
    lambda with
    implicit this

    View Slide

  67. html {

    table {

    for (product in products) {

    tr {

    td { text(product.description) }

    td { text(product.price) }

    td { text(product.popularity) }

    }

    }

    }

    }
    HTML Builders
    lambdas with receiver

    View Slide

  68. val db: SQLiteDatabase = …
    db.beginTransaction()

    try {

    db.delete("users", "first_name = ?", arrayOf("Jake"))

    db.setTransactionSuccessful()

    } finally {

    db.endTransaction()

    }
    db.inTransaction {

    delete("users", "first_name = ?", arrayOf("Jake"))

    }
    Avoiding Duplication

    View Slide

  69. db.beginTransaction()

    try {

    db.delete("users", "first_name = ?", arrayOf("Jake"))

    db.setTransactionSuccessful()

    } finally {

    db.endTransaction()

    }
    db.inTransaction {

    delete("users", "first_name = ?", arrayOf("Jake"))

    }
    Inline functions
    is declared as
    inline function
    generated bytecode is similar to

    View Slide

  70. ANKO-DSL
    DSL for dynamic layouts

    View Slide

  71. Alerts
    fun Activity.showAreYouSureAlert(process: () -> Unit) {

    alert(title = "Are you sure?",

    message = "Are you really sure?") {

    positiveButton("Yes") { process() }

    negativeButton("No") { }

    }.show()

    }
    Are you sure?
    Are you really sure?
    No Yes

    View Slide

  72. customView {

    verticalLayout {

    val email = editText {

    hint = "Email"

    }


    val password = editText {

    hint = "Password"

    transformationMethod =
    PasswordTransformationMethod.getInstance()

    }


    positiveButton("Log In") {

    logIn(email.text, password.text)

    }

    }

    }
    Password
    Log In
    Email
    Custom layouts

    View Slide

  73. kotlinlang.org

    View Slide

  74. Gradle & Kotlin
    Writing Gradle build scripts
    and plugins in Kotlin

    View Slide

  75. try.kotlinlang.org

    View Slide

  76. Kotlin Koans

    View Slide

  77. View Slide

  78. Have a nice Kotlin!

    View Slide