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

Welcome to Kotlin Wonderland!

Magda Miu
November 27, 2019

Welcome to Kotlin Wonderland!

Kotlin promises concise, expressive and safe code. The presentation will include a full tour of language basics, we will have some fun with functions and will learn new keywords from the Kotlin Wonderland. We will discover the main advantages of Kotlin compared to Java and we will explore the inventive features Kotlin offers for working with classes. This talk is suitable for every developer who is looking for a modern and secure language to use in developing awesome apps.

Magda Miu

November 27, 2019
Tweet

More Decks by Magda Miu

Other Decks in Programming

Transcript

  1. What is Kotlin? • General-purpose • FP + OOP •

    Open source (Apache 2.0) • Developed by JetBrains • Static typing
  2. 2010 Project started 2016 Kotlin 1.0 2017 Official on Android

    2018 Kotlin 1.3 Aug 2019 Kotlin 1.3.50 Nov 2019 Kotlin 1.3.60 Kotlin timeline
  3. Kotlin popularity In the latest Stack Overflow developer survey, it

    ranks as the 4th most loved programming language.
  4. Current adoption Since the release of Kotlin 1.0 in 2016,

    the number of users has risen to 2.2M.
  5. Kotlin in numbers 57% of users use Kotlin in production

    154,525,768 lines of code written in Kotlin on GitHub
  6. Conventions • The same conventions like on Java • Uppercase

    for types • Lower camelCase for methods and properties • Semicolons are optional • Reverse notation for packages ◦ A file could contain multiple classes ◦ The folder names not have to match the package name
  7. Development tools • JDK ◦ JVM 1.6+ • Kotlin Compiler

    • Editor or IDE ◦ IntelliJ IDEA, Android Studio, NetBeans, Eclipse
  8. *.kt *.java Kotlin compiler Java compiler *.class *.jar App Kotlin

    is 100% interoperable with Java Kotlin runtime
  9. val vs var • val is immutable (read-only) and you

    can only assign a value to them exactly one time. • var is mutable and can be reassigned. // immediate assignment val countOfEvenNumbers: Int = 10 // `Int` type is inferred var sumOfNumbers = 0 // type required when no initializer is provided var countOfPrimeNumbers: Int // deferred assignment countOfPrimeNumbers = 3 countOfPrimeNumbers = 24
  10. String interpolation • Simple reference uses $ • Complex references

    uses ${} • Raw Strings """ val firstWord = "Learn " val secondWord = "Kotlin" var bothWords = "$firstWord $secondWord" println("$bothWords has ${bothWords.length}") println(""""$bothWords" has ${bothWords.length}""")
  11. Null safety • In an effort to rid the world

    of NullPointerException, variable types in Kotlin don't allow the assignment of null. • In order to use a variable that can be null, declare it nullable by adding ? at the end of its type.
  12. But wait... The only possible causes of NPE's may be:

    • An explicit call to throw NullPointerException() • Usage of the !! operator (not-null assertion operator) • Some data inconsistency with regard to initialization • Java interoperation
  13. // check for null in conditions val trainingName: String? =

    "Learn Kotlin in 45 minutes" if (trainingName != null && trainingName.isNotEmpty()) { print("String of length ${trainingName.length}") } else { print("Empty string") }
  14. val platform: String? = null val language = "Kotlin" println(platform?.length)

    // safe call println(language.length) // unnecessary safe call val lengthOfWord = platform!!.length // !! operator val numberOfLetters: Int? = lengthOfWord as? Int // safe cast
  15. val platform: String? = null val language = "Kotlin" println(platform?.length)

    // safe call println(language.length) // unnecessary safe call val lengthOfWord = platform!!.length // !! operator val numberOfLetters: Int? = lengthOfWord as? Int // safe cast
  16. val platform: String? = null val language = "Kotlin" println(platform?.length)

    // safe call println(language.length) // unnecessary safe call val lengthOfWord = platform!!.length // !! operator val numberOfLetters: Int? = lengthOfWord as? Int // safe cast
  17. // Elvis operator val name: String? = null val lengthOfName

    = name?.length ?: -1 println(lengthOfName)
  18. // Elvis operator val name: String? = null val lengthOfName

    = name?.length ?: -1 println(lengthOfName) // => -1
  19. fun add(a: Int, b: Int): Int { return a +

    b } Function name Parameters Return type Function body
  20. // equivalent Kotlin syntax fun add(a: Int, b: Int): Int

    { return a + b } fun add(a: Int, b: Int): Int = a + b fun add(a: Int, b: Int) = a + b
  21. // equivalent Kotlin syntax fun add(a: Int, b: Int): Int

    { return a + b } fun add(a: Int, b: Int): Int = a + b fun add(a: Int, b: Int) = a + b
  22. // equivalent Kotlin syntax fun add(a: Int, b: Int): Int

    { return a + b } fun add(a: Int, b: Int): Int = a + b fun add(a: Int, b: Int) = a + b
  23. // named arguments fun getFullName(firstName: String, lastName: String): String {

    return "$firstName $lastName" } getFullName(lastName = "Miu", firstName = "Magda")
  24. class Utility { // infix functions = functions with a

    single parameter infix fun String.onto(other: String) = Pair(this, other) } fun main(args: Array<String>) { val blueShoes = "blue".onto("shoes") val yellowScarf = "yellow" onto "scarf" println(blueShoes) // => (blue, shoes) println(yellowScarf) // => (yellow, scarf) }
  25. // functions with varargs parameters fun varargExample(vararg names: Int) {

    println("Argument has ${names.size} elements") } varargExample() // => Argument has 0 elements varargExample(1) // => Argument has 1 elements varargExample(1, 2, 3) // => Argument has 3 elements
  26. // high order function = fun with fun or fun

    returns a fun fun add(a: Int, b: Int): Int { return a + b } fun returnAddFunction(): ((Int, Int) -> Int) { return ::add }
  27. Lambda • A lambda expression or an anonymous function is

    a “function literal”, i.e. a function that is not declared, but passed immediately as an expression • A lambda expression is always surrounded by curly braces • Its parameters (if any) are declared before -> (parameter types may be omitted) • The body goes after -> (when present)
  28. val sum: (Int, Int) -> Int = { a, b

    -> a + b } println(sum(3,4))
  29. val sum: (Int, Int) -> Int = { a, b

    -> a + b } println(sum(3,4)) // => 7
  30. // returning from a lambda val calculateGrade = { grade

    : Int -> when(grade) { in 0..40 -> "Fail" !is Int -> "Just a grade" in 41..70 -> "Pass" in 71..100 -> "Distinction" else -> false } } println(calculateGrade(57))
  31. // returning from a lambda val calculateGrade = { grade

    : Int -> when(grade) { in 0..40 -> "Fail" !is Int -> "Just a grade" in 41..70 -> "Pass" in 71..100 -> "Distinction" else -> false } } println(calculateGrade(57)) // => Pass
  32. Extension functions • An extension function is a member function

    of a class that is defined outside the class. • Extensions are resolved statically and can also be defined with the class type that is nullable. • If a class contains a companion object, then we can also define extension functions and properties for the companion object.
  33. Class • There are primary and secondary constructors. For secondary

    we should add the keyword constructor • The primary constructor cannot contain any code.
  34. class Person(val fullName: String) { val age: Int get() {

    return 18 } // secondary constructor constructor(fullName: String, age: Int) : this(fullName) {} } // instance of the class val john = Person("John", 24)
  35. Inheritance • Inheritance: use open keyword for class • Overriding

    methods and properties: use the open modifier open class Person { open val name = "Tom" open fun displaySkills() { } } // inheritance and override class Student : Person() { override val name = "Jerry" override fun displaySkills(){ } }
  36. // "object" keyword can be used to create singleton objects.

    object TheObject { fun hello() = "hello" override fun toString() = "Hello, it's me, ${TheObject::class.simpleName}" } fun useSingletonObject() { println(TheObject.hello()) // => hello val someRef: Any = TheObject println(someRef) // => Hello, it's me, TheObject }
  37. Delegation • Composition over Inheritance design pattern • Native support

    for delegation (implicit delegation) • Zero boilerplate code
  38. interface PetAction { fun eat() } interface PetColor { val

    color: String } object YellowColor : PetColor { override val color = "yellow" }
  39. class PrintingPetAction(val food: String) : PetAction { override fun eat()

    { println(food) } } class Cat(petColor: PetColor = YellowColor) : PetAction by PrintingPetAction("eats a lot of fish"), PetColor by petColor
  40. class PrintingPetAction(val food: String) : PetAction { override fun eat()

    { println(food) } } class Cat(petColor: PetColor = YellowColor) : PetAction by PrintingPetAction("eats a lot of fish"), PetColor by petColor
  41. fun delegate() { val kittyCat = Cat() println("Pet has color

    ${kittyCat.color}") kittyCat.eat() } fun main(args: Array<String>) { delegate() } // => Pet has color yellow // => eats a lot of fish
  42. Data classes are a concise way to create classes that

    just hold data. Data classes Function Price Getters and Setters 0 Lei equals() & hashCode() 0 Lei toString() 0 Lei componentN() 0 Lei copy() 0 Lei TOTAL FREE!
  43. data class Character(val name: String, val age: Int) fun main()

    { val mickeyMouse = Character("Mickey Mouse", 82) val mickeyMouseToday = mickeyMouse.copy(age = 83) // destructuring declarations val (name, age) = mickeyMouseToday println("$name, $age years of age") mickeyMouseToday.component1() // => name mickeyMouseToday.component2() // => age }
  44. Companion object • companion object: syntactically it's similar to the

    static methods in Java class Person { companion object { fun callMe() = "Call" } } // Person.callMe()
  45. // immutable list and mutable list val numbersList = listOf("one",

    "two", "three") val mutableNumbersList = mutableListOf("one", "two", "three") listOf(1, 5, 3).sum() // => 9 listOf("a", "b", "cc").sumBy { it.length } // => 4 List
  46. // immutable set and mutable set val colors = setOf("red",

    "blue", "yellow") val mutableColors = mutableSetOf("red", "blue", "yellow") val longerThan3 = colors.filter { it.length > 3 } // => [blue, yellow] Set
  47. // immutable map and mutable map val desserts = hashMapOf("whipped

    cream" to "cake", "chocolate" to "cookie") println(desserts["chocolate"]) val inventory = mutableMapOf("pancake" to 1) inventory.put("cake", 3) inventory.remove("pancake") Map
  48. // Sequences represent lazily-evaluated collections. val fooSequence = generateSequence(1, {

    it + 1 }) val x = fooSequence.take(10).toList() println(x) // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] Sequence
  49. Main advantages of Kotlin • Readability ◦ A code is

    clean if it is easy to understand • Interoperability ◦ Q: “Can I use my existing libraries?” ◦ A: “Yes, absolutely!” • Safety ◦ Prevents some specific type of errors (NPE) • Tooling ◦ Kotlin is a compiled language (IntelliJ IDEA, Android Studio, NetBeans, Eclipse)
  50. Best practices 1. Agree on conventions beforehand 2. Don’t treat

    it as Java with a different syntax 3. Use a linter (like ktlint) 4. Embrace the immutability 5. Reconsider if you need to use !! operator 6. Don’t hide too much info 7. Choose readable over short expressions