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

Kotlin Deep Dive Devoxx

Guy Heylens
November 06, 2017

Kotlin Deep Dive Devoxx

The slides from my Kotlin Deep Dive talk @ Devoxx 2017.

Guy Heylens

November 06, 2017
Tweet

More Decks by Guy Heylens

Other Decks in Technology

Transcript

  1. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin: The Why • Started in

    2010 by Jetbrains • A language that • Safe and Approachable • Concise • Pragmatic
  2. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin: Timeline 0 2000000 4000000 6000000

    8000000 10000000 12000000 2010 2012 2013 2014 2015 2016 2017 2018 Kotlin is born Release 1.0 Gradle Spring Official Android Release 1.1 Dedicated Kotlin support for Spring 5.0 LOC
  3. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin: The What • Statically typed

    language • Inspired by Java, Groovy, Scala, C#, amongst others • Open source • Targets • JVM / Android • Javascript • Native
  4. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin: The What • What can

    we do? • Industrial applications • Mobile • Client side • Web • Desktop • Server side (Backend)
  5. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin Conventions • Follows the Java

    Programming Language Coding Conventions • Types start with Uppercase • Methods and Properties in lower camelCase • Semicolons are (almost) optional • Packages follow the reverse notation • be.kotlin.training.basics • Package does not have to match the folder name.
  6. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin Tooling • JDK 1.6 +

    • Kotlin compiler • Editor or IDE • IntelliJ Idea, Android Studio, Eclipse
  7. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi fun Keyword Kotlin in .... minutes

    • Functions fun max(a: Int, b: Int): Int { return if(a > b) a else b }
  8. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi fun Keyword Parameters Kotlin in ....

    minutes • Functions fun max(a: Int, b: Int): Int { return if(a > b) a else b }
  9. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi fun Keyword Return type Parameters Kotlin

    in .... minutes • Functions fun max(a: Int, b: Int): Int { return if(a > b) a else b }
  10. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Function body fun Keyword Return type

    Parameters Kotlin in .... minutes • Functions fun max(a: Int, b: Int): Int { return if(a > b) a else b }
  11. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Statements

    and expressions Kotlin if is an expression as most other control structures, except for the loops. Java all control structures are statements
  12. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Statements

    and expressions Kotlin if is an expression as most other control structures, except for the loops. Java all control structures are statements Expression vs Statement has a value can be used as a part of another expression has no value always top level element
  13. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Functions

    fun max(a: Int, b: Int) = if (a > b) a else b No return type declaration!
  14. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Variables

    var myValue: Int var myValue: Int = 10 val myValue: String val myValue: String = “Hello, world!”
  15. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Variables

    var myValue: Int var myValue: Int = 10 val myValue: String val myValue: String = “Hello, world!” Initializer expression
  16. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Variables

    Mutable and Immutable variables val => value “immutable” Can’t be reassigned
  17. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Variables

    Mutable and Immutable variables val => value “immutable” Can’t be reassigned final in Java
  18. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Variables

    Mutable and Immutable variables var => variable “mutable” val => value “immutable” Can’t be reassigned final in Java
  19. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Variables

    Mutable and Immutable variables var => variable “mutable” val => value “immutable” Can’t be reassigned final in Java Can be reassigned
  20. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Variables

    Mutable and Immutable variables var => variable “mutable” val => value “immutable” Can’t be reassigned final in Java Can be reassigned regular (non-final) Java variable
  21. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Variables

    val message: String if (canPerformOperation()) { message = "Success" // ... perform the operation } else { message = "Failed" }
  22. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes val myValue:

    String = “Hello, world!” == val myValue = “Hello, world!” Type inference:
  23. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes String templates

    val name : String = “John” val age : Int = 35 val s = “My name is $name and my age is $age”
  24. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes String templates

    val name : String = “John” val age : Int = 35 val s = “My name is $name and my age is $age”
  25. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes String templates

    val name : String = “John” val age : Int = 35 val s = “My name is $name and my age is $age”
  26. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes val name

    : String = “John” val s = “My name is $name and my name length is {$name.length}” String templates
  27. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes val s

    = “””This is a multiline string. It’s fun. Try it.””” String templates
  28. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi val s = “””This is a

    multiline |string. |It’s fun. |Try it.”””.trimMargin() Kotlin in .... minutes String templates
  29. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi val s = “””This is a

    multiline |string. |It’s fun. |Try it.”””.trimMargin() Kotlin in .... minutes .trimMargin(“>”) String templates
  30. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Ranges

    and loops rangeTo val range = 1 .. 4 val start = 1 val end = 4 val otherRange = start .. end downTo val range = 4 downTo 1 val start = 4 val end = 1 val otherRange = start downTo end
  31. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • for

    loops for(a: Int in 1..100){ println(a) } for(a in 100 downTo 1){ println(a) } for(b in 100 downTo 1 step 5){ println(b) }
  32. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • for

    loops val cities = listOf(“Brussels”, “Antwerp”, “Ghent”, “Hasselt”) for(city in cities){ println(city) }
  33. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • while

    loops var i = 100 while(i > 0){ i -- } var x = 10 do{x -- println(x) } while (x > 6)
  34. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • break

    out of a loop for(a: Int in 1..100){ for(b: Int in 1..100){ if(b % a == 0){ //break out of the loop! } } }
  35. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • break

    out of a loop loop@ for(a: Int in 1..100){ for(b: Int in 1..100){ if(b % a == 0){ break @loop } } }
  36. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • break

    out of a loop loop@ for(a: Int in 1..100){ for(b: Int in 1..100){ if(b % a == 0){ break @loop } } } THIS IS NOT A GOTO!
  37. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Classes

    Modifier Class member Top-level declaration public (default) Visible everywhere Visible everywhere internal Visible in a module Visible in a module protected Visible in subclasses - private Visible in a class Visible in a file
  38. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Classes

    /* Java */ public class Person { private final String name; public Person(String name) { this.name = name; } public String getName() { return name; } }
  39. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Repetitive code Kotlin in .... minutes

    • Classes /* Java */ public class Person { private final String name; public Person(String name) { this.name = name; } public String getName() { return name; } }
  40. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Classes

    class Person( val name: String, var isMarried: Boolean ) Read-only property: generates a field and a trivial getter
  41. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Classes

    class Person( val name: String, var isMarried: Boolean ) Writeable property: generates a field, a getter and a setter Read-only property: generates a field and a trivial getter
  42. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Classes

    //custom getters and setters class Person(val id: Int, var name: String, val yearOfBirth: Int){ val age: Int get() = Calendar.getInstance().get(Calendar.YEAR) - yearOfBirth var socialSecurityNumber: String = "" set(value) { if(!value.startsWith("SN")){ throw IllegalArgumentException("Social security number should start with SN") } field = value } //function in a class fun personAsString(){ println("Id: $id - Name: $name - Birthdate: $yearOfBirth ") } }
  43. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Classes

    //custom getters and setters class Person(val id: Int, var name: String, val yearOfBirth: Int){ val age: Int get() = Calendar.getInstance().get(Calendar.YEAR) - yearOfBirth var socialSecurityNumber: String = "" set(value) { if(!value.startsWith("SN")){ throw IllegalArgumentException("Social security number should start with SN") } field = value } //function in a class fun personAsString(){ println("Id: $id - Name: $name - Birthdate: $yearOfBirth ") } }
  44. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Classes

    //custom getters and setters class Person(val id: Int, var name: String, val yearOfBirth: Int){ val age: Int get() = Calendar.getInstance().get(Calendar.YEAR) - yearOfBirth var socialSecurityNumber: String = "" set(value) { if(!value.startsWith("SN")){ throw IllegalArgumentException("Social security number should start with SN") } field = value } //function in a class fun personAsString(){ println("Id: $id - Name: $name - Birthdate: $yearOfBirth ") } }
  45. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Classes

    //custom getters and setters class Person(val id: Int, var name: String, val yearOfBirth: Int){ val age: Int get() = Calendar.getInstance().get(Calendar.YEAR) - yearOfBirth var socialSecurityNumber: String = "" set(value) { if(!value.startsWith("SN")){ throw IllegalArgumentException("Social security number should start with SN") } field = value } //function in a class fun personAsString(){ println("Id: $id - Name: $name - Birthdate: $yearOfBirth ") } } //field (reserved word) is the backing field of the property
  46. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Classes

    data class Customer (var id: Int, var name: String, var email: String) public class CustomerJava { private int id; private String name; private String email; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public @NotNull String neverNull(){ return "a string"; } public String sometimesNull(){ return "a string"; } public void prettyPrint(){ System.out.printf("Id: %d - Name %s", id, name); } @Override public String toString() { return "CustomerJava{" + "id=" + id + ", name='" + name + '\'' + ", email='" + email + '\'' + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; CustomerJava that = (CustomerJava) o; if (id != that.id) return false; if (name != null ? !name.equals(that.name) : that.name != null) return false; return email != null ? email.equals(that.email) : that.email == null; } @Override public int hashCode() { int result = id; result = 31 * result + (name != null ? name.hashCode() : 0); result = 31 * result + (email != null ? email.hashCode() : 0); return result; } }
  47. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Classes

    // 0 (zero) based enums enum class Priority{ MINOR, NORMAL, MAJOR, CRITICAL } enum class PriorityValue(val value: Int){ MINOR(-1){ override fun toString(): String { return "Minor priority" } }, NORMAL(0), MAJOR(1), CRITICAL(100); }
  48. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Classes

    • First class citizens in Kotlin → objects first • Provide expected functionality such as properties and functions • There are no fields, only properties • We have access to properties if required in custom getters / setters • Data classes provide functionality to reduce boiler-plate code • Each enum is an instance and allows behaviour
  49. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Interfaces

    • Same as in Java with a few twists • Allows to have default implementations (same as Java 8) • Is different from an abstract class because: • it cannot hold a state • a class can implement multiple interfaces when it cannot inherit from 
 multiple abstract classes
  50. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Interfaces

    interface Interface1 { fun funA(){ println("Interface 1 says Hello") } } interface Interface2 { fun funA(){ println("Interface 2 says Hello") } }
  51. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Interfaces

    interface Interface1 { fun funA(){ println("Interface 1 says Hello") } } interface Interface2 { fun funA(){ println("Interface 2 says Hello") } } class Class1and2: Interface1, Interface2{ override fun funA() { //refer with the super keyword super<Interface2>.funA() super<Interface1>.funA() } }
  52. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • filter

    and map val list = listOf(1, 2, 3, 4) println(list.filter { it % 2 == 0 }) // output [2, 4]
  53. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • filter

    and map data class Person(val age: Int, val name: String) val people = listOf(Person( 29, "Alice"), Person( 31, "Bob")) println(people.filter { it.age > 30 }) // output [Person(name=Bob, age=31)]
  54. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • map

    val list = listOf(1, 2, 3, 4) println(list.map { it * it }) // output [1, 4, 9, 16]
  55. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • map

    val people = listOf(Person("Alice", 29), Person("Bob", 31)) people.filter { it.age > 30 }.map(Person::name)
  56. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Conditional

    flow var myString = "test" if(myString != " "){ println("Not empty") } else if(myString.startsWith("a")){ println("string starts with an A") } else { println("Empty") }
  57. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Conditional

    flow when(result){ is String -> println("Excellent") is Int -> println("Number") "Value" -> println("Is a value") }
  58. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Conditional

    flow var x = 2 when (x) { 1 -> print("x == 1") 2 -> print("x == 2") else -> { print("x is neither 1 nor 2") } }
  59. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Conditional

    flow when (x) { 0, 1 -> print("x == 0 or 1") else -> print("neither 0 nor 1") } val validNumbers = 1..19 when (x) { in 1..10 -> print("x is in the range") in validNumbers -> print("x is valid") !in 10..20 -> print("x is outside the range") else -> print("none of the above") }
  60. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Extension function Receiver type Kotlin in

    .... minutes • Extensions fun String.lastChar(): Char = this.get(this.length - 1)
  61. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Extensions

    fun String.capStuff(): String { return this.toUpperCase() } fun String.prefixStuff(prefix: String): String { return "$prefix $this" } fun main(args: Array<String>) { println(“Batman".capStuff()) // Prints out “BATMAN” println("Robin".prefixStuff("Hey").capStuff()) // Prints out “HEY ROBIN” }
  62. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Interoperable

    • Navigate between Java and Kotlin source files. • Debug mixed language projects and step between code written in different languages. • Refactor your Java methods and have their use in Kotlin code correctly updated, and vice versa.
  63. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Interoperable

    fun main(args: Array<String>) { val customer = CustomerJava() customer.email = "[email protected]" customer.prettyPrint() /* * Runnable is a Java interface. Through lambdas we are directly passing the println method. * */ val runnable = Runnable {println("Invoking runnable")} }
  64. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Interoperable

    fun main(args: Array<String>) { val customer = CustomerJava() customer.email = "[email protected]" customer.prettyPrint() /* * Runnable is a Java interface. Through lambdas we are directly passing the println method. * */ val runnable = Runnable {println("Invoking runnable")} }
  65. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi • Interoperable Kotlin in .... minutes

    fun main(args: Array<String>) { val kr = KotlinRepo() val customerJava = kr.getById(10) customerJava.id } //inherit from Java class PersonKotlin: PersonJava(){ } class KotlinRepo: CustomerRepository{ override fun getById(id: Int): CustomerJava { TODO("not implemented") //To change body of created functions use File | Settings | File Templates. } override fun getAll(): MutableList<CustomerJava> { TODO("not implemented") //To change body of created functions use File | Settings | File Templates. } }
  66. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi • Interoperable Kotlin in .... minutes

    fun main(args: Array<String>) { val kr = KotlinRepo() val customerJava = kr.getById(10) customerJava.id } //inherit from Java class PersonKotlin: PersonJava(){ } class KotlinRepo: CustomerRepository{ override fun getById(id: Int): CustomerJava { TODO("not implemented") //To change body of created functions use File | Settings | File Templates. } override fun getAll(): MutableList<CustomerJava> { TODO("not implemented") //To change body of created functions use File | Settings | File Templates. } }
  67. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Null

    safety class KotlinRepo: CustomerRepository{ override fun getById(id: Int): CustomerJava? { TODO("not implemented") //To change body of created functions use File | Settings | File Templates. } override fun getAll(): MutableList<CustomerJava>? { TODO("not implemented") //To change body of created functions use File | Settings | File Templates. } }
  68. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Null

    safety class KotlinRepo: CustomerRepository{ override fun getById(id: Int): CustomerJava? { TODO("not implemented") //To change body of created functions use File | Settings | File Templates. } override fun getAll(): MutableList<CustomerJava>? { TODO("not implemented") //To change body of created functions use File | Settings | File Templates. } }
  69. @guyheylens #Devoxx #kotlindeepdive https://github.com/kugbel/Devoxx17RestApi Kotlin in .... minutes • Interoperable

    public static void main(String[] args) { CustomerKotlin customerKotlin = new CustomerKotlin(1, "Guy", "[email protected]"); customerKotlin.setEmail(“[email protected]”); String value = customerKotlin.someField; customerKotlin.changeStatus(Status.Current); //check the default parameter customerKotlin.changeStatus(); //Annotation set name for Java. customerKotlin.Preferential(); try { customerKotlin.loadStatistics("filename"); } catch (IOException e) { e.printStackTrace(); } //Invoke Top Level Function //Like Kotlin created a static class with a static method. //TopLevelFunctionsKt.prefix("some", "value"); UtilityClass.prefix("some", "value"); UtilityClass.getCopyrightYear(); //Talking to the extension function it requires an instance of the class "customerKotlin" CustomerKotlinKt.extensions(customerKotlin, "Test"); } data class CustomerKotlin (var id: Int, var name: String, var email: String){ @JvmField val someField = "Value" override fun toString():String{ return "{\"id\": \"$name\", \"name\": \"$name\"}" } @JvmOverloads fun changeStatus(status: Status = Status.Current){ } @JvmName("Preferential") fun makePrefered(){ } @Throws(IOException::class) fun loadStatistics(filename: String){ if(filename == ""){ throw IOException("Filename can not be empty") } } }