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

IDCamp Sharing Session - Kotlin 101

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers. →

IDCamp Sharing Session - Kotlin 101

Avatar for Eko Suhariyadi

Eko Suhariyadi

November 02, 2019

More Decks by Eko Suhariyadi

Other Decks in Programming

Transcript

  1. What is Kotlin • Open source and free to use

    Programming language by JetBrains • Targeting Java Platform: server-side, Android, anywhere Java runs • Statically typed Language • Object Oriented and Functional Language • First-class functions • Immutability • No side-effects • Pragmatic, Concise, Safe And Focus on Interoperability
  2. Kotlin History • Internal project in JetBrains unveiled in July

    2011 after 1 year development • Seeking language for future development • Scala is great, but compile time and interoperability is obvious deficiency • Open sourced on Feb 2012 • First v1.0 released on 15 Feb 2016 
 (takes 6 years for first stable release) • Named after Kotlin Island, near St. Petersburg, Russia
 Where most JetBrains’ Kotlin development team work • “Some part” of language design is based on “Effective Java” book by 
 Joshua Bloch
  3. Fun Facts • C takes 1 year to first stable

    release • C++ takes 4 years • Java takes 4 years • Python takes 3 years • Javascript only takes 10 days :D
 #DuaMingguJadi
  4. Why Kotlin? • (Android) Stuck on Java 6 • No

    streams • No lambda, method references • No try-with-resources
  5. Why Kotlin? • (Android) Stuck on Java 6 • No

    streams Use RxJava(2) • No lambda, method references • No try-with-resources
  6. Why Kotlin? • (Android) Stuck on Java 6 • No

    streams Use RxJava(2) • No lambda, method references Recent Partial Java 8 Desugar Support • No try-with-resources
  7. Why Kotlin? • (Android) Stuck on Java 6 • No

    streams Use RxJava(2) • No lambda, method references Recent Partial Java 8 Desugar Support • No try-with-resources minSdkVersion = 19 or Use Retrolambda
  8. Why Kotlin? • (Android) Stuck on Java 6 • Inability

    to add methods to platform types in Java • Achieved by Util class • Nullability problems (*NullPointerException) in Java • General verbosity / boilerplate code in Java • Too much code to achieve minimal jobs
  9. Taste of Kotlin data class Person( val name: String, val

    age: Int? = null ) fun main() { val persons = listOf( Person("Alice"), Person("Bob", age = 33) ) val oldest = persons.maxBy { it.age ?: 0 } println("The oldest is: $oldest") } // The oldest is: Person(name=Bob, age=33) Data class Nullable type (Int?); default value for argument Top-level function Named argument Lambda expression; Elvis operator String template Autogenerated toString
  10. Taste of Kotlin • Property declaration • val (*value) for

    immutable property, once initialised can’t be changed • var (*variable) for mutable property, can be reassigned with new “data” • fun keyword to declare method/function • So literally we are having fun when code in Kotlin
  11. Taste of Kotlin fun someFunction(): Unit { // function always

    have return value var say: String = "Kotlin is pragmatic language" say = "also safe and concise" val hello: String = "Domo arigatou Mr. Roboto" hello = "Konnichiwa" // compile time error return Unit } fun sum(x: Int, y: Int): Int { return x + y }
  12. Taste of Kotlin fun someFunction() { // function always have

    return value var say = "Kotlin is pragmatic language" say = "also safe and concise" val hello = "Domo arigatou Mr. Roboto" hello = "Konnichiwa" // compile time error } fun sum(x: Int, y: Int): Int { return x + y }
  13. Taste of Kotlin fun someFunction() { // function always have

    return value var say = "Kotlin is pragmatic language" say = "also safe and concise" val hello = "Domo arigatou Mr. Roboto" hello = "Konnichiwa" // compile time error } fun sum(x: Int, y: Int) = x + y // one-liner
  14. Working with Null data class Contact( var name: String, var

    email: String? = null ) fun main() { val eko = Contact( name = "Eko Suhariyadi", email = "[email protected]" ) eko.name = null // compile error, because name is non null String eko.email = null // ok, since email is nullable String }
  15. Working with Null val eko = Contact("Eko Suhariyadi") // return

    other value when email is null; using elvis operator val email = eko.email ?: "email unavailable" // cascading null safety val emailStrSize = eko.email?.length // safe scoping eko.email?.let { // this is only executed when email is not null // send email }
  16. Data Class • Write POJO class in Java is quite

    verbose • Overloading constructor • Getter & setter • toString • hashCode & equals • IDE could help for code generation • Or by using libraries such as AutoValue or Immutable
  17. Data Class public class Todo { private String description; private

    Long createdAt; private boolean done; public Todo(String description, Long createdAt, boolean done) { this.description = description; this.createdAt = createdAt; this.done = done; } // ... }
  18. Data Class public class Todo { private String description; private

    Long createdAt; private boolean done; public Todo(String description, Long createdAt, boolean done) { this.description = description; this.createdAt = createdAt; this.done = done; } public Todo(String description, Long createdAt) { this.description = description; this.createdAt = createdAt; this.done = true; } // … }
  19. Data Class public class Todo { private String description; private

    Long createdAt; private boolean done; public Todo(String description, Long createdAt, boolean done) { this.description = description; this.createdAt = createdAt; this.done = done; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public Long getCreatedAt() { return createdAt; } public void setCreatedAt(Long createdAt) { this.createdAt = createdAt; } public boolean isDone() { return done; } public void setDone(boolean done) { this.done = done; } // ... }
  20. Data Class import java.util.Objects; public class Todo { private String

    description; private Long createdAt; private boolean done; public Todo(String description, Long createdAt, boolean done) { this.description = description; this.createdAt = createdAt; this.done = done; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public Long getCreatedAt() { return createdAt; } public void setCreatedAt(Long createdAt) { this.createdAt = createdAt; } public boolean isDone() { return done; } public void setDone(boolean done) { this.done = done; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Todo)) return false; Todo todo = (Todo) o; return done == todo.done && Objects.equals(description, todo.description) && Objects.equals(createdAt, todo.createdAt); } @Override public int hashCode() { return Objects.hash(description, createdAt, done); } @Override public String toString() { return "Todo{" + "description='" + description + '\'' + ", createdAt=" + createdAt + ", done=" + done + '}'; } }
  21. Data Class \> javap TodoKotlin Compiled from "TodoKotlin.kt" public final

    class TodoKotlin { public final java.lang.String getDescription(); public final void setDescription(java.lang.String); public final long getCreatedAt(); public final void setCreatedAt(long); public final boolean getDone(); public final void setDone(boolean); public TodoKotlin(java.lang.String, long, boolean); public TodoKotlin(java.lang.String, long, boolean, int, kotlin.jvm.internal.DefaultConstructorMarker); public TodoKotlin(java.lang.String, long); public final java.lang.String component1(); public final long component2(); public final boolean component3(); public final TodoKotlin copy(java.lang.String, long, boolean); public static TodoKotlin copy$default(TodoKotlin, java.lang.String, long, boolean, int, java.lang.Object); public java.lang.String toString(); public int hashCode(); public boolean equals(java.lang.Object); }
  22. Data Class • Kotlin data class generate compiled code almost

    same with Java POJO • But with steroid (extra method) • component(N) for destructure • copy for prototype pattern
  23. Data Class val todo = TodoKotlin("Sample Todo", System.currentTimeMillis(), false) val

    (description, createAt, finished) = todo // destructure val (description1, _, finished1) = todo // destructure specific field(s) // create new object by cloning from other val cloneTodo = todo.copy(description = "Clone Sample Todo", done = true)
  24. Extension Functions • Ability to add functions or properties to

    existing class without modify the class itself • In Java, we usually using static Utility classes
  25. Extension Functions // ViewGroupUtils.java public static View inflate(ViewGroup parent, int

    layoutResId) { return LayoutInflater.from(parent.getContext()) .inflate(layoutResId, parent, false); } @Override ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { final View rootView = ViewGroupUtils.inflate(parent, viewType); return new ViewHolder(rootView); }
  26. Extension Functions // Kotlin fun ViewGroup.inflate(layoutResId: Int): View = LayoutInflater.from(this.context)

    .inflate(layoutResId, this, false) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val rootView = parent.inflate(viewType) return ViewHolder(rootView) }
  27. Lambda Expression • Implementation • Event listener, Callbacks • Higher-order

    functions • With Kotlin’s perks • Can be inlined for performant custom control structure • Closures
  28. Lambda Expression // Java Observable.just("Hello Rx") .subscribe( new Consumer<String>() {

    @Override public void accept(String s) throws Exception { System.out.println(s); } }, new Consumer<Throwable>() { @Override public void accept(Throwable throwable) throws Exception { throwable.printStackTrace(); } }, new Action() { @Override public void run() throws Exception { System.out.println("Completed"); } });
  29. Lambda Expression // Kotlin Observable.just("Hello Rx") .subscribe( { s ->

    println(s) }, { throwable -> throwable.printStackTrace() }, { println("Completed") })
  30. Higher-order Functions fun listCalculator(numbers: List<Int>, calculator: (List<Int>) -> Int): Int

    = calculator(numbers) fun main() { val numbers = (1..10).toList() val sum = listCalculator(numbers, { var accumulator = 0 it.forEach { accumulator += it } accumulator }) val avg = listCalculator(numbers, { var accumulator = 0 it.forEach { accumulator += 1 } accumulator / numbers.size }) println("sum=$sum, avg=$avg")
  31. Higher-order Functions fun listCalculator(numbers: List<Int>, calculator: (List<Int>) -> Int): Int

    = calculator(numbers) fun main() { val numbers = (1..10).toList() val sum = listCalculator(numbers) { var accumulator = 0 it.forEach { accumulator += it } accumulator } val avg = listCalculator(numbers) { var accumulator = 0 it.forEach { accumulator += 1 } accumulator / numbers.size } println("sum=$sum, avg=$avg") } When function is last parameter We can do this
  32. Extension Function Expressions • Recap • Extension Functions -> Functions

    added to a Type/Class without modifying the original • Function Expressions -> Undeclared function bodies used as an expression (ie. data/ value) • Higher-order Functions -> Function which takes functions as parameter and or returns a function
  33. Extension Function Expressions db.beginTransaction() try { db.delete("movie", "title = ?",

    arrayOf("Rurouni Kenshin")) db.markTransactionSuccessful() } finally { db.endTransaction() }
  34. Extension Function Expressions fun SQLiteDatabase.useTransaction(func: () -> Unit) { beginTransaction()

    try { func() markTransactionSuccessful() } finally { endTransaction() } }
  35. Extension Function Expressions db.beginTransaction() try { db.delete("movie", "title = ?",

    arrayOf("Rurouni Kenshin")) db.markTransactionSuccessful() } finally { db.endTransaction() }
  36. Extension Function Expressions fun SQLiteDatabase.useTransaction(func: () -> Unit) { beginTransaction()

    try { func() markTransactionSuccessful() } finally { endTransaction() } }
  37. Extension Function Expressions fun SQLiteDatabase.useTransaction(func: (SQLiteDatabase) -> Unit) { beginTransaction()

    try { func(this) markTransactionSuccessful() } finally { endTransaction() } }
  38. Extension Function Expressions fun SQLiteDatabase.useTransaction(func: (SQLiteDatabase) -> Unit) { beginTransaction()

    try { func(this) markTransactionSuccessful() } finally { endTransaction() } }
  39. Extension Function Expressions fun SQLiteDatabase.useTransaction(func: SQLiteDatabase.() -> Unit) { beginTransaction()

    try { this.func() markTransactionSuccessful() } finally { endTransaction() } }
  40. Extension Function Expressions fun SQLiteDatabase.useTransaction(func: SQLiteDatabase.() -> Unit) { beginTransaction()

    try { this.func() markTransactionSuccessful() } finally { endTransaction() } }
  41. Extension Function Expressions inline fun SQLiteDatabase.useTransaction(func: SQLiteDatabase.() -> Unit) {

    beginTransaction() try { func() markTransactionSuccessful() } finally { endTransaction() } } // with inline keyword, code block will be inlined with caller code // so, there in no overhead for creating lambda
  42. Extension Function Expressions • Higher-order functions is very convenience to

    create our own DSL • For Android developer • There is anko library, but sadly no longer being maintain • Jetpack Kotlin extension
  43. Other Kotlin Cool • Collection API • Standar lib functions

    • apply, with, let, run • If Expressions • When Expression • Sealed class