Upload
others
View
95
Download
5
Embed Size (px)
Citation preview
Kotlin - Intro
● Replacement for Java● Multiplatform● .kt
Kotlin - Hello World
● Top level declaration● No class● println moved to stdlib● Semicolon● fun● Unit vs void● Optional args in main● public is default
public class Hey { public static void main(String[] args) { System.out.println("Hello World!"); }}
fun main() { println("Hello World!")}
Kotlin - Interoperability
● 100% interoperable with Java
● Calling Java directly from Kotlin
○ and vice versa
● Can have both in the same project
(but not in the same file)
Kotlin - Variables
val x = 5var y = "Foo"
x = 6y = "Bar"
Val cannot be reassigned
val x: Int = 5var y: String = "Foo"
Kotlin - Functions (cont.)
fun add(x: Int, y: Int): Int { return x + y}
fun add(x: Int, y: Int) = x + y
Standard function declaration
Expression function
Kotlin - Functions: Extension functions
public class StringUtils { public static char middle(String s) { return s.charAt(s.length() / 2); }}
String s = "hello";char mid = StringUtils.middle(s);
fun String.middle() = get(length / 2)
val s = "hello"val mid = s.middle()
Extends the functionality of a class
Kotlin - String Templates
● String Templates are expressions that is evaluated
and concatenated in a String
val s = "abc"println("$s.length is ${s.length}")
>> abc.length is 3
Basert på
https://developer.android.com/training/basics/firstapp/creating-project
Control Flow
Kotlin - if
fun maxOf(a: Int, b: Int): Int { if (a > b) { return a } else { return b }}
fun maxOf(a: Int, b: Int) = if (a > b) a else b
Expression Function
Kotlin - when
when(x) { 0 -> print("Zero") 1 -> print("One") 2 -> print("Two") 3 -> print("Three") 4 -> print("Four") 5 -> print("Five") 6 -> print("Six") 7 -> print("Seven") 8 -> print("Eight") 9 -> print("Nine") else -> { print("What?") }}
● Think Switch Case in Java● Expression; not a statement● Exhaustive matching
Kotlin - for
val items = listOf("IN2000", "is", "cool")
for (item in items) { println(item)}
for ((index, value) in items.withIndex()) { println("$index : $value")}
Kotlin - for (cont.)
for (i in 6 downTo 0 step 2) { println(i)}
>> 6>> 4>> 2>> 0
for (i in 1..3) { println(i)}
>> 1>> 2>> 3
Kotlin - while
val items = listOf("IN2000", "is", "cool")var index = 0
while (index < items.size) { println("item at $index is ${items[index]}") index++}
Basert på
https://developer.android.com/training/basics/firstapp/creating-project
Null safety
Kotlin - Null safety
“ I call it my billion-dollar
mistake. It was the
invention of the null
reference in 1965 ”
- Tony Hoare -
Kotlin - Null safety (cont.)
● What is null?○ Pointer to nothing?
● Where does this fit into the type system?● One of the most common causes of crashes in Java
Kotlin - Nullable types (cont.)
val x: String = null
val x: String? = null
Error: Null can not be a value of a non-null type String
Kotlin - Smart casting (cont.)
val x: String? = null
if (x == null) { // Can't use members of b in here} else { println(x.length)}
Basert på
https://developer.android.com/training/basics/firstapp/creating-project
Collections
Kotlin - Standard collections
Immutable MutableList<T> MutableList<T>
Set<T> MutableSet<T>
Map<K, V> MutableMap<K, V>
Array<T>
Kotlin - Standard collections (cont.)
Immutable MutablelistOf() mutableListOf()
setOf() mutableSetOf()
mapOf() mutableMapOf()
arrayOf()
Kotlin - Collection interfaces
https://kotlinlang.org/docs/reference/collections-overview.html
Basert på
https://developer.android.com/training/basics/firstapp/creating-project
Classes and Objects
Kotlin - Class: Constructors
● Primary constructor
● Secondary constructor
● Primary constructor with properties
● init block
Kotlin - Class: Secondary Constructor
class Person { val age: Int constructor(age: Int) { this.age = age }}
Kotlin - Class: Primary Constructor with property
● Fields in primary constructor● No need for getters and setters
class Person(val age: Int)
Kotlin - Class: Init
● Init will run when object is created● Can have multiple init blocks● Can be used for complicated initialization logic
class Person(val age: Int) { init { println("Creating person with age: $age") }}
public class Person {
private String name; private int age;
public Person(String name, int age) { this.name = name; this.age = age; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
@Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; }
@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return age == person.age && Objects.equals(name, person.name); }
@Override public int hashCode() { return Objects.hash(name, age); }}
Kotlin - POJO Class
Kotlin - Getters and Setters
● Why do we have them in Java?● Encapsulation● Auto-generated, but also customizable
var stringRepresentation: Stringget() = this.toString()set(value) {
setDataFromString(value) }
Kotlin - Getters and Setters interoperability
public class Person {
private String name;
public Person(String name) {this.name = name;
}
public String getName() {return name;
}
public void setName(String name) {
this.name = name;}
}
val person = Person("Alice")
person.name // Same as person.getName()
person.name = "Bob" // Same as person.setName("Bob")
Kotlin - Inheritance
● : both used for extends and implements
● Classes and fields are final by default
● Uses primary constructor instead of super() when extending
open class Base(p: Int)
class Derived(p: Int) : Base(p)
Kotlin - Inheritance (cont.)
● override is a keyword
open class Shape { open fun draw() { /*...*/ } fun fill() { /*...*/ }}
class Circle() : Shape() { override fun draw() { /*...*/ }}
Kotlin - Sealed classes
● An abstract class with known inheritors
● Exhaustive matching with when
sealed class Exprdata class Const(val number: Double) : Expr()data class Sum(val e1: Expr, val e2: Expr) : Expr()object NotANumber : Expr()
Kotlin - Objects
● Used to create Singletons● Managing state● Lazily initialized
object DataProviderManager { fun registerDataProvider(provider: DataProvider) { // ... }
val allDataProviders: Collection<DataProvider> get() = // ...}
Kotlin - Companion Objects
Object declared inside a class
class MyClass { companion object { fun create(): MyClass = MyClass() }}
val instance = MyClass.create() Called like this
● Alternative to static
Kotlin - Nested Class
Classes can be nested into other classes
class Outer { private val bar: Int = 1 class Nested { fun foo() = 2 }}
val demo = Outer.Nested().foo()
>> 2
Kotlin - Inner Class
An inner class can access members of its outer class
class Outer { private val bar: Int = 1 inner class Inner { fun foo() = bar }}
val demo = Outer().Inner().foo()
>> 1
Kotlin - Anonymous Objects
● Made with the use of Object Expression● Used a lot in Android Studio
○ For instance: onClickListener()
window.addMouseListener(object : MouseAdapter() {
override fun mouseClicked(e: MouseEvent) { ... }
override fun mouseEntered(e: MouseEvent) { ... }})
Kotlin - Enums
● Class with known possible values● Type-safety
enum class Direction { NORTH, SOUTH, WEST, EAST}
Kotlin - Why we need enums
fun move(pos: Pair<Int, Int>, direction: String) = when (direction) { "NORTH" -> pos.first to pos.second+1 "SOUTH" -> pos.first to pos.second-1 "WEST" -> pos.first-1 to pos.second "EAST" -> pos.first+1 to pos.second }
‘when’ expression must be exhaustive, add necessary ‘else’ branch
Kotlin - Why we need enums (cont.)
fun move(pos: Pair<Int, Int>, direction: String) = when (direction) { "NORTH" -> pos.first to pos.second+1 "SOUTH" -> pos.first to pos.second-1 "WEST" -> pos.first-1 to pos.second "EAST" -> pos.first+1 to pos.second else -> throw IllegalArgumentException() }
Kotlin - Why we need enums (cont.)
fun move(pos: Pair<Int, Int>, direction: Direction) = when (direction) { Direction.NORTH -> pos.first to pos.second+1 Direction.SOUTH -> pos.first to pos.second-1 Direction.WEST -> pos.first-1 to pos.second Direction.EAST -> pos.first+1 to pos.second }
enum class Direction { NORTH, SOUTH, WEST, EAST}
Kotlin - Enums with properties
enum class Color(val rgb: Int) { RED(0xFF0000), GREEN(0x00FF00), BLUE(0x0000FF)}
Basert på
https://developer.android.com/training/basics/firstapp/creating-project
Operator overloading and destructuring
Kotlin - Operator overloading
● Defines what an operator cando for other types
● Looks after a function that is modified
● unaryMinus() → unary negation function
data class Point(val x: Int, val y: Int)
operator fun Point.unaryMinus() = Point(-x, -y)
val point = Point(10, 20)
fun main() { println(-point)}
>> Point(x=-10, y=-20)
Kotlin - Destructuring
● Convenient syntax● Often used in loops
val (name, age) = person
val name = person.component1()val age = person.component2()
val name = person.nameval age = person.age
Basert på
https://developer.android.com/training/basics/firstapp/creating-project
Functional Kotlin
Functional - What is functional programming?
● A paradigm
● Style
● Focus on functions
● Higher orders functions
● Immutable values
Functional - Functional languages
● ML
○ Haskell
○ Elm
● Lisp
○ Clojure
● Multi Paradigm
○ Kotlin
○ Scala
Kotlin - Functional programming
“ [...] functional programming can be viewed as a style of programming in which the basic method of computation is the application of functions to arguments.”
- Hutton, Graham (2005). Programming in Haskell.
Functional - In general
● Function as a value○ Higher order functions
● Pure functions○ No side effects
● Anonymous functions (lambda)
● Function composition
Programming without side-effects
● How do we change a value?
● Make a new one!
● What about more complex data structures?
var x = 5x += 1
val x = 5val y = x + 1
Without side-effectsWith side-effects
Functional Kotlin - In this course
● Functional in the LARGE○ Managed effects
○ Monads
● Functional in the SMALL
○ Higher order functions
○ Limited mutations
● We program functional in the SMALL
Kotlin - Higher Order Function
● Takes a function as a parameter
fun repeat(times: Int, action: (Int) -> Unit)
repeat(3) { println("Hello")}
>> Hello>> Hello>> Hello
repeat(0) { error("We should not get here!")}
>>
Kotlin - Lambda Expressions
val add: (Int, Int) -> Int = { x: Int, y: Int -> x + y }
val add = { x, y -> x + y } Without annotations
● Arguments and body are separated with an arrow● Annotations are optional● Can span multiple lines● Return value is the last expression in the body
Kotlin - Lambda type signature
● (Int) -> String
● Parameters in parentheses
● Return-type after arrow (→)
● Read as “from Int to String”
● val onClick: () -> Unit
● val add: (Int, Int) -> Int
Kotlin - Working with Immutable Lists
fun squareList(items: List<Int>): List<Int> { val newItems = mutableListOf<Int>() for (item in items) { newItems += item * item } return newItems}
squareList(listOf(1, 2, 3))
>> [1, 4, 9]
Kotlin - Map Filter Fold
listOf(1, 2, 3).map { it + 1 }
>> [2, 3, 4]
listOf(1, 2, 3).filter { it % 2 == 0 }
>> [2]
listOf(1, 2, 3).fold(1) { acc, e -> acc * e }
>> 6
Kotlin - Map Filter Fold (cont.)
val sumSquareEven = items .map { it * it } .filter { it % 2 == 0 } .fold(0) { a, v -> a + v }
Kotlin - Map Filter Fold (cont.)
val square = { x: Int -> x * x }val isEven = { x: Int -> x % 2 == 0 }val sumSquareEven = items .map(square) .filter(isEven) .fold(0, Int::plus) // or just sum()
Kotlin - Map Filter Fold (type signatures)
fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R>
fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T>
fun <T, R> Iterable<T>.fold(initial: R, operation: (acc: R, T) -> R): R
Basert på
https://developer.android.com/training/basics/firstapp/creating-project
Scope functions
Kotlin - let
● The context object is available as an argument (it)● The return value is the lambda result● Useful in combination with ?.
fun <T, R> T.let(block: (T) -> R): R
val str: String? = "Hello"val length = str?.let { println("calculating length of $it") it.length}
Kotlin - run
● The context object is available as a receiver (this)● The return value is the lambda result
fun <T, R> T.run(block: T.() -> R): R
val str: String? = "Hello"val length = str?.run { println("calculating length of $this") length}
Kotlin - with
● The context object is passed as an argument ● Available as a receiver (this) inside the lambda● Return value is the lambda result
with (person) { println("Name: $name") println("Age: $age")}
fun <T, R> with(receiver: T, block: T.() -> R): R
Kotlin - apply
● The context object is available as a receiver (this)● The return value is the object itself
fun <T> T.apply(block: T.() -> Unit): T
val adam = Person("Clark").apply { age = 32 city = "Denver"}
Kotlin - also
● The context object is available as an argument (it)● The return value is the object itself
fun <T> T.also(block: (T) -> Unit): T
val numbers = mutableListOf("one", "two", "three")numbers .also { println("Elements before adding: $it") } .add("four")
>> Elements before adding: [one, two, three]
Kotlin - Flowchart
Source: https://medium.com/@elye.project/mastering-kotlin-standard-functions-run-with-let-also-and-apply-9cd334b0ef84
Basert på
https://developer.android.com/training/basics/firstapp/creating-project
Summary
Kotlin - Summary
● Forces you to make better decisions
○ Mutability
○ open, override, sealed classes
○ exhaustive matching
● Null safety
● Expression based
● Supports a functional style
Kotlin
Slides and examples are based on the official Kotlin documentation
https://kotlinlang.org/docs/reference/