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

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. 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;
 }
 }
  2. - equals - hashCode - toString 
 data 
 class

    Person(val name: String, val age: Int)
  3. 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()
  4. 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
  5. 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, /*...*/; }
  6. 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
 }
 // ...
 }
  7. 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)
 } // ...
 }
  8. fun updateWeather(degrees: Int) {
 val (description, colour) =
 if (degrees

    < 5) {
 Pair("cold", BLUE)
 } else if (degrees < 23) {
 Pair("mild", ORANGE)
 } else {
 Pair("hot", RED)
 } // ...
 }
  9. fun updateWeather(degrees: Int) {
 val (description, colour) = when {


    degrees < 5 -> Pair("cold", BLUE)
 degrees < 23 -> Pair("mild", ORANGE)
 else -> Pair("hot", RED)
 } // ...
 }
  10. fun updateWeather(degrees: Int) {
 val (description, colour) = when {


    degrees < 5 -> "cold" to BLUE
 degrees < 23 -> "mild" to ORANGE
 else -> "hot" to RED
 }
 }
  11. 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;
 }
  12. 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 ✗
  13. val length = if (s != null) s.length else null

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

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

    val s: String? Nullability operators val length: Int = s?.length ?: 0
  16. Annotate your Java types in Kotlin Type behaves like regular

    Java type @Nullable @NotNull Type Type? Type Type @ParametersAreNonnullByDefault @MyNonnullApi Type/Type?
  17. class Optional<T>(val value: T) { 
 fun isPresent() = value

    != null
 
 fun get() = value ?:
 throw NoSuchElementException("No value present") } Nullable types ≠ Optional
  18. you can avoid any repetition you can make the code

    look nicer you can create API looking like DSL expressive
  19. fun String.lastChar() = get(length - 1) this can be omitted

    Extension Functions fun String.lastChar() = this.get(this.length - 1)
  20. 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");
  21. 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?
  22. infix fun <A, B> A.to(that: B) = Pair(this, that) "ANSWER".to(42)

    "hot" to RED mapOf(0 to "zero", 1 to "one") The to extension function
  23. { employee: Employee -> employee.city == City.PRAGUE } What’s an

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

    with collections with Lambdas val employees: List<Employee> data class Employee( val city: City, val age: Int ) extension functions employees.filter { it.city == City.PRAGUE }.map { it.age }.average()
  25. Kotlin library: extensions on collections • filter • map •

    reduce • count • find • any • flatMap • groupBy • …
  26. 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()

  27. 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
  28. with (sb) {
 appendln("Alphabet: ")
 ...
 } inline fun <T,

    R> with( receiver: T, block: T.() -> R ): R = receiver.block() The with function declaration
  29. Lambda with receiver val sb = StringBuilder()
 with (sb) {


    appendln("Alphabet: ")
 for (c in 'a'..'z') {
 this.append(c)
 }
 } lambda with implicit this
  30. html {
 table {
 for (product in products) {
 tr

    {
 td { text(product.description) }
 td { text(product.price) }
 td { text(product.popularity) }
 }
 }
 }
 } HTML Builders lambdas with receiver
  31. 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
  32. 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
  33. 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
  34. 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