Introduction to Kotlin Riyadh Java Meetup Nov 2019 Mohammad Hewedy mhewedy @mohewedy 1 2
Agenda ● What is Kotlin? ● Language Features ● Demos 2
If I were writing a Spring app today, I would strongly consider Kotlin. It brings the same kind of simplification to Java code as Spring did to J2EE. Rod Johnson. 3
What is Kotlin? ● Statically with type inference and strongly typed(1). ● Multi paradigm (object-oriented and functional) ● Fully Interoperate with Java ● Mainly targets the JVM (targets other runtimes as well) ● Semicolons are optional ● Type comes after the variable (val age: Int = 30) (1) see appendix 1 4
What is Kotlin? ● val keyword used to declare immutable variables ● var keyword used to declare mutable variables ● Classes and class members are public by default ● Classes and methods are final by default ● open keyword used to mark class as extensible and method as overridable 5
What is Kotlin? ● Interface methods are abstract and open by default ● Has package-level functions as well as class-level functions ● Supports extension functions to patch any library classes with new functionality (a.k.a Monkey patching) ● Support limited set of operator overloading using operator keyword 6 operator fun String.not() = this.reversed() println(!"hello") // prints olleh
What is Kotlin? ● Functions in kotlin supports: ○ default arguments ○ named arguments ○ variable-length argument lists ● data classes provides: ○ equals()/hashCode() ○ toString() ○ componentN() functions ○ copy() ○ Destructuring declarations: val (name, age) = jane ● Multiline strings with string interpolation ● Delegated Properties that allows lazy variable evaluation 7
What is Kotlin? ● object used to declare objects, which might used as: ○ singletons ○ companion object ○ Anonymous classes ● Access modifiers: ○ public ○ private ○ protected ○ internal ● Can use to write Domain-Specific Languages (DSL) ● Has Tail call optimization (tail recursion) 8
Code or Data? 9 config { datasource { url = "jdbc:h2:mem" username = "root" } webservice { wsdl = "http://example.org/ws?wsdl" action = "urn:weather-ws" } } source: https://gist.github.com/mhewedy/88d0f63486101501c3d87ff9d2e0231b
Code as Data 10 fun main() { val config = Config() config { datasource { url = "jdbc:h2:mem" username = "root" } webservice { wsdl = "http://example.org/ws?wsdl" action = "urn:weather-ws" } } println(config) } source: https://gist.github.com/mhewedy/88d0f63486101501c3d87ff9d2e0231b
Language Features 11
If as an expression ● Traditional usage: 12 var max = a if (a < b) max = b
If as an expression ● Traditional usage with else: 13 var max: Int if (a > b) { max = a } else { max = b }
If as an expression ● As an expression 14 val max = if (a > b) a else b
If as an expression ● As an expression 15 val max = if (a > b) { print("choose a") a } else { print("choose b") b }
When expression 16 when (x) { 1 -> print("x == 1") 2 -> print("x == 2") else -> { // Note the block print("x is neither 1 or 2") } }
When expression 17 when (x) { in 1..10 -> print("x is in range") in validNumbers -> print("x is valid") !in 10..20 -> print("x is outside the range3") else -> print("none of the above") }
When expression 18 fun hasPrefix(x: Any) = when (x) { is String -> x.startsWith("prefix") // note the smart cast else -> false }
When expression 19 when { x.isOdd() -> print("x is in the range") x.isEven() -> print("x is even") else -> print("x is funny") }
When expression ● when scoped variables: 20 fun Request.getBody() = when (val response = executeRequest()) { is Success -> response.body is HttpError -> throw HttpException(response.status) }
For Loops ● For loops used to for iterates through anything that provides an iterator, which means: ○ has a member- or extension-function iterator(), whose return type: ■ has a member- or extension-function next(), and ■ has a member- or extension-function hasNext() that returns Boolean. 21
For Loops 22 for (item: Int in ints) { }
For Loops 23 for (i in 1..3) { println(i) }
For Loops 24 for (i in 6 downTo 0 step 2) { println(i) }
For Loops 25 for (i in 6.downTo(0).step(2)) { println(i) }
Loops and labels ● Kotlin has while loops as well ● Both for and while loops support break and continue (w/o labels) 26 loop@ for (i in 1..10) { for (j in 1..10) { if (...) break@loop } }
For Loops 27 var counter = 0 operator fun Int.iterator() = this operator fun Int.next() = this operator fun Int.hasNext() = counter++ < this // usage: for (n in 20) { println(n) }
Classes 28 class Person constructor(firstName: String)
Classes 29 class Person(val name: String) { var children: MutableList<Person> = mutableListOf(); constructor(name: String, parent: Person) : this(name) { parent.children.add(this) } }
Classes 30 class DontCreateMe private constructor() {/* */ }
Classes 31 val invoice = Invoice() val customer = Customer("Joe Smith")
32 Type Hierarchy
Inheritance 33 class Example // implicitly inherits from Any
Inheritance 34 open class Base(p: Int) class Derived(p: Int) : Base(p)
Inheritance 35 class MyView : View { constructor(ctx: Context) : super(ctx) constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs) }
Inheritance 36 open class Polygon { open fun draw() {} } abstract class Rectangle : Polygon() { abstract override fun draw() }
Inheritance 37 open class Shape { open fun draw() {/* ... */} fun fill() {/* ... */ } } class Circle : Shape() { override fun draw() {/* ... */} }
Inheritance 38 typealias NodeList = ArrayList<Node> sealed class Node object EmptyNode : Node() data class ValueNode(val value: Any?) : Node() data class ObjectNode(val props: ArrayList<Pair<String, Any?>>) : Node() data class ArrayNode(val elements: NodeList) : Node() source: https://github.com/mhewedy/eureka-klient/blob/de7a1bf2ebec72a3bc1c9ca32868f5d93da32765/src/main/kotlin/helpers/json/Deserializer.kt#L30
Inheritance 39 fun eval(expr: Node): Unit = when (expr) { is ValueNode -> println(expr.value) // smart case is ObjectNode -> println(expr.props) is ArrayNode -> expr.elements.forEach { eval(it) } is EmptyNode -> print("empty") // the `else` clause is not required }
Properties and Fields 40 class State(val name: String) class Address { var name: String = "Holmes, Sherlock" var state: State? = null } // used as val address = Address() println("${address.name} at ${address.state?.name}") // note the safe navigation operator with nullable types
Properties and Fields 41 class MyClass { lateinit var subject: TestSubject @Setup fun setup() { subject = TestSubject() } @Test fun test() { subject.method() // dereference directly } }
Interfaces 42 interface MyInterface { fun foo() fun bar() { // optional body } }
Interfaces 43 interface A{ fun foo() { print("A") } fun bar() } interface B{ fun foo() { print("B") } fun bar() { print("bar") } } class C : A { override fun bar() { print("bar") } } class D: A, B { override fun foo() { super<A>.foo() super<B>.foo() } override fun bar() { super.bar() } }
Functions 44 fun double(x: Int): Int { return 2 * x }
Functions 45 fun double(x: Int): Int = x * 2
Functions 46 fun double(x: Int) = x * 2
Functions 47 fun foo(vararg strings: String) { /* ... */} // calling as foo(strings = *arrayOf("a", "b", "c"))
Functions 48 fun read(b: Array<Byte>, off: Int = 0, len: Int = b.size) { /* ... */ }
Functions 49 fun reformat( str: String, normalizeCase: Boolean = true, upperCaseFirstLetter: Boolean = true, divideByCamelHumps: Boolean = false, wordSeparator: Char = ' ' ) { /* ... */ } // calling as reformat(str, normalizeCase = true, upperCaseFirstLetter = true, divideByCamelHumps = false, wordSeparator = '_') // can shuffle args as well
Functions 50 infix fun Int.shl(x: Int): Int { /* ... */ } // calling the function using the infix notation 1 shl 2 // is the same as 1.shl(2)
Functions 51 fun dfs(graph: Graph) { fun dfs(current: Vertex, visited: MutableSet<Vertex>) { if (!visited.add(current)) return for (v in current.neighbors) dfs(v, visited) } dfs(graph.vertices[0], HashSet()) }
Functions 52 class Sample { fun foo() { print("Foo") } }
Functions ● Classes and objects can extend functions 53 object Identity : (Int) -> Int { override fun invoke(p1: Int) = p1 } // called as Identity(10)
Functions ● Lambda with receiver 54 operator fun Config.invoke(block: Config.() -> Unit) { block.invoke(this) }
Functions 55 fun add(x: Int): (Int) -> Int { return fun(y: Int): Int { return x + y } } val result = add(10)(30)
Functions 56 fun add(x: Int): (Int) -> Int { return { y: Int -> x + y } } val addFunc = add(10) val result = addFunc(30)
Functions 57 fun add(x: Int): (Int) -> Int { return { x + it } } val addFunc = add(10) val result = addFunc(30)
Functions 58 fun <T> map(x: String, op: (String) -> T): T { return op(x) } // used as map("John Smith", fun(n: String): Int { return n.length })
Functions 59 fun <T> map(x: String, op: (String) -> T): T { return op(x) } // used as map("John Smith", { it.length })
Functions 60 fun <T> map(x: String, op: (String) -> T): T { return op(x) } // used as map("John Smith") { it.length }
Functions 61 fun <E> List<E>.test(op: (e: E) -> Boolean): List<E> { val ret = arrayListOf<E>() for (element in this) { if (op(element)) ret += element } return ret } // used as employees.test { it.age > 25 }
Functions ● fold is one of most important functional operators 62 fun <T, R> Collection<T>.fold( initial: R, combine: (acc: R, nextElement: T) -> R ): R { var accumulator: R = initial for (element: T in this) { accumulator = combine(accumulator, element) } return accumulator }
fold (a.k.a reduce): how it works 63source: http://perugini.cps.udayton.edu/teaching/books/PL/www/lecture_notes/currying.html
Collections 64
Collections 65 val numbers = mutableListOf("one", "two", "three", "four") numbers += "five" val immutableNumbers = listOf("one", "two", "three", "four") immutableNumbers += "five" // compilation error
Collection Operations ● Transformations ○ Mapping (map) ○ Zipping (zip) ○ Flattening (flatmap) ● Filtering ○ Filtering (filter) ○ Partitioning (partition) ○ Testing predicates (any, none, all) ● Plus and Minus 66
Collection Operations ● Grouping ○ Group By (groupBy) ● Retrieving Collection Parts ○ Take and drop (takeWhile, dropWhile, takeLast, dropLast, take(n), drop(n)) ○ Partitioning (partition) ○ Testing predicates (any, none, all) ● Retrieve: ○ At index: (elementAt, []) ○ By condition: (first, last, find, findLast) 67
Collection Operations ● Order: ○ Sorting: (sortBy, sortedByDescending, reversed, shuffled) ● Aggregate: ○ Built-in: min, max, average, sum, count, maxBy, minBy ○ Custom: reduce, fold 68
So, How to start? 69
Write your test cases in Kotlin 70 @Test fun `Test getContentType for image pdf byte stream`() { val pdfBytes = byteArrayOf(0x25, 0x50, 0x44, 0x46, 0x2d, 0x31, 0x2e, 0x34) // %PDF-1.4 val contentType = StreamUtil. getContentType(ByteArrayInputStream(pngPdfBytes), "abc.png") //give invalid name assertThat(contentType).isEqualTo("application/pdf") }
Test Spring Apps 71 @Test fun `test calling translateToCategories will calculate the agent category correctly`() { // setup val agentRepository = mock(AgentRepository::class.java) val agentCategoryRepository = mock(AgentCategoryRepository::class.java) whenever(agentRepository.findAllById(any())) .thenReturn(listOf(createAgentOfExperience(10), createAgentOfExperience(5))) whenever(agentCategoryRepository.findAll()).thenReturn(dbLookup()) val carrierService = CarrierService(agentRepository, agentCategoryRepository) // SUT // when val translatedList: List<Long> = carrierService.translateToCategories() // then assertThat(translatedList).asList().containsExactlyInAnyOrder(CAT_5, CAT_6) }
Demo 72
● https://github.com/mhewedy/eureka-klient (pure Kotlin app) ● https://gitlab.com/ticketz/ticketz-api (Kotlin + spring boot) ● https://github.com/mhewedy/condition-engine (Kotlin + java + spring boot) 73
Appendix 74
1. Strong vs Weak types 75 // Kotlin (strong typed) fun main() { val x: Float = 10.5f val y: Int = x // compilation error println("y = $y") } // C (weak typed) #include <stdio.h> int main() { float x = 10.5; int y = x; printf("y = %dn", y); // prints 10 }
Resources 76
Resources ● https://www.wikiwand.com/en/Kotlin_(programming_language) ● https://kotlinlang.org/docs/reference/ (very good resource) ● http://shop.oreilly.com/product/0636920052982.do ● http://shop.oreilly.com/product/0636920052999.do ● https://www.manning.com/books/kotlin-in-action ● https://medium.com/sngular-devs/from-closures-to-curry-and-compose-197d2abcadd8 77
Thanks. 78

Introduction to kotlin + spring boot demo

  • 1.
    Introduction to Kotlin Riyadh JavaMeetup Nov 2019 Mohammad Hewedy mhewedy @mohewedy 1 2
  • 2.
    Agenda ● What isKotlin? ● Language Features ● Demos 2
  • 3.
    If I werewriting a Spring app today, I would strongly consider Kotlin. It brings the same kind of simplification to Java code as Spring did to J2EE. Rod Johnson. 3
  • 4.
    What is Kotlin? ●Statically with type inference and strongly typed(1). ● Multi paradigm (object-oriented and functional) ● Fully Interoperate with Java ● Mainly targets the JVM (targets other runtimes as well) ● Semicolons are optional ● Type comes after the variable (val age: Int = 30) (1) see appendix 1 4
  • 5.
    What is Kotlin? ●val keyword used to declare immutable variables ● var keyword used to declare mutable variables ● Classes and class members are public by default ● Classes and methods are final by default ● open keyword used to mark class as extensible and method as overridable 5
  • 6.
    What is Kotlin? ●Interface methods are abstract and open by default ● Has package-level functions as well as class-level functions ● Supports extension functions to patch any library classes with new functionality (a.k.a Monkey patching) ● Support limited set of operator overloading using operator keyword 6 operator fun String.not() = this.reversed() println(!"hello") // prints olleh
  • 7.
    What is Kotlin? ●Functions in kotlin supports: ○ default arguments ○ named arguments ○ variable-length argument lists ● data classes provides: ○ equals()/hashCode() ○ toString() ○ componentN() functions ○ copy() ○ Destructuring declarations: val (name, age) = jane ● Multiline strings with string interpolation ● Delegated Properties that allows lazy variable evaluation 7
  • 8.
    What is Kotlin? ●object used to declare objects, which might used as: ○ singletons ○ companion object ○ Anonymous classes ● Access modifiers: ○ public ○ private ○ protected ○ internal ● Can use to write Domain-Specific Languages (DSL) ● Has Tail call optimization (tail recursion) 8
  • 9.
    Code or Data? 9 config{ datasource { url = "jdbc:h2:mem" username = "root" } webservice { wsdl = "http://example.org/ws?wsdl" action = "urn:weather-ws" } } source: https://gist.github.com/mhewedy/88d0f63486101501c3d87ff9d2e0231b
  • 10.
    Code as Data 10 funmain() { val config = Config() config { datasource { url = "jdbc:h2:mem" username = "root" } webservice { wsdl = "http://example.org/ws?wsdl" action = "urn:weather-ws" } } println(config) } source: https://gist.github.com/mhewedy/88d0f63486101501c3d87ff9d2e0231b
  • 11.
  • 12.
    If as anexpression ● Traditional usage: 12 var max = a if (a < b) max = b
  • 13.
    If as anexpression ● Traditional usage with else: 13 var max: Int if (a > b) { max = a } else { max = b }
  • 14.
    If as anexpression ● As an expression 14 val max = if (a > b) a else b
  • 15.
    If as anexpression ● As an expression 15 val max = if (a > b) { print("choose a") a } else { print("choose b") b }
  • 16.
    When expression 16 when (x){ 1 -> print("x == 1") 2 -> print("x == 2") else -> { // Note the block print("x is neither 1 or 2") } }
  • 17.
    When expression 17 when (x){ in 1..10 -> print("x is in range") in validNumbers -> print("x is valid") !in 10..20 -> print("x is outside the range3") else -> print("none of the above") }
  • 18.
    When expression 18 fun hasPrefix(x:Any) = when (x) { is String -> x.startsWith("prefix") // note the smart cast else -> false }
  • 19.
    When expression 19 when { x.isOdd()-> print("x is in the range") x.isEven() -> print("x is even") else -> print("x is funny") }
  • 20.
    When expression ● whenscoped variables: 20 fun Request.getBody() = when (val response = executeRequest()) { is Success -> response.body is HttpError -> throw HttpException(response.status) }
  • 21.
    For Loops ● Forloops used to for iterates through anything that provides an iterator, which means: ○ has a member- or extension-function iterator(), whose return type: ■ has a member- or extension-function next(), and ■ has a member- or extension-function hasNext() that returns Boolean. 21
  • 22.
    For Loops 22 for (item:Int in ints) { }
  • 23.
    For Loops 23 for (iin 1..3) { println(i) }
  • 24.
    For Loops 24 for (iin 6 downTo 0 step 2) { println(i) }
  • 25.
    For Loops 25 for (iin 6.downTo(0).step(2)) { println(i) }
  • 26.
    Loops and labels ●Kotlin has while loops as well ● Both for and while loops support break and continue (w/o labels) 26 loop@ for (i in 1..10) { for (j in 1..10) { if (...) break@loop } }
  • 27.
    For Loops 27 var counter= 0 operator fun Int.iterator() = this operator fun Int.next() = this operator fun Int.hasNext() = counter++ < this // usage: for (n in 20) { println(n) }
  • 28.
  • 29.
    Classes 29 class Person(val name:String) { var children: MutableList<Person> = mutableListOf(); constructor(name: String, parent: Person) : this(name) { parent.children.add(this) } }
  • 30.
  • 31.
    Classes 31 val invoice =Invoice() val customer = Customer("Joe Smith")
  • 32.
  • 33.
    Inheritance 33 class Example //implicitly inherits from Any
  • 34.
    Inheritance 34 open class Base(p:Int) class Derived(p: Int) : Base(p)
  • 35.
    Inheritance 35 class MyView :View { constructor(ctx: Context) : super(ctx) constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs) }
  • 36.
    Inheritance 36 open class Polygon{ open fun draw() {} } abstract class Rectangle : Polygon() { abstract override fun draw() }
  • 37.
    Inheritance 37 open class Shape{ open fun draw() {/* ... */} fun fill() {/* ... */ } } class Circle : Shape() { override fun draw() {/* ... */} }
  • 38.
    Inheritance 38 typealias NodeList =ArrayList<Node> sealed class Node object EmptyNode : Node() data class ValueNode(val value: Any?) : Node() data class ObjectNode(val props: ArrayList<Pair<String, Any?>>) : Node() data class ArrayNode(val elements: NodeList) : Node() source: https://github.com/mhewedy/eureka-klient/blob/de7a1bf2ebec72a3bc1c9ca32868f5d93da32765/src/main/kotlin/helpers/json/Deserializer.kt#L30
  • 39.
    Inheritance 39 fun eval(expr: Node):Unit = when (expr) { is ValueNode -> println(expr.value) // smart case is ObjectNode -> println(expr.props) is ArrayNode -> expr.elements.forEach { eval(it) } is EmptyNode -> print("empty") // the `else` clause is not required }
  • 40.
    Properties and Fields 40 classState(val name: String) class Address { var name: String = "Holmes, Sherlock" var state: State? = null } // used as val address = Address() println("${address.name} at ${address.state?.name}") // note the safe navigation operator with nullable types
  • 41.
    Properties and Fields 41 classMyClass { lateinit var subject: TestSubject @Setup fun setup() { subject = TestSubject() } @Test fun test() { subject.method() // dereference directly } }
  • 42.
    Interfaces 42 interface MyInterface { funfoo() fun bar() { // optional body } }
  • 43.
    Interfaces 43 interface A{ fun foo(){ print("A") } fun bar() } interface B{ fun foo() { print("B") } fun bar() { print("bar") } } class C : A { override fun bar() { print("bar") } } class D: A, B { override fun foo() { super<A>.foo() super<B>.foo() } override fun bar() { super.bar() } }
  • 44.
  • 45.
  • 46.
  • 47.
    Functions 47 fun foo(vararg strings:String) { /* ... */} // calling as foo(strings = *arrayOf("a", "b", "c"))
  • 48.
    Functions 48 fun read(b: Array<Byte>,off: Int = 0, len: Int = b.size) { /* ... */ }
  • 49.
    Functions 49 fun reformat( str: String, normalizeCase:Boolean = true, upperCaseFirstLetter: Boolean = true, divideByCamelHumps: Boolean = false, wordSeparator: Char = ' ' ) { /* ... */ } // calling as reformat(str, normalizeCase = true, upperCaseFirstLetter = true, divideByCamelHumps = false, wordSeparator = '_') // can shuffle args as well
  • 50.
    Functions 50 infix fun Int.shl(x:Int): Int { /* ... */ } // calling the function using the infix notation 1 shl 2 // is the same as 1.shl(2)
  • 51.
    Functions 51 fun dfs(graph: Graph){ fun dfs(current: Vertex, visited: MutableSet<Vertex>) { if (!visited.add(current)) return for (v in current.neighbors) dfs(v, visited) } dfs(graph.vertices[0], HashSet()) }
  • 52.
    Functions 52 class Sample { funfoo() { print("Foo") } }
  • 53.
    Functions ● Classes andobjects can extend functions 53 object Identity : (Int) -> Int { override fun invoke(p1: Int) = p1 } // called as Identity(10)
  • 54.
    Functions ● Lambda withreceiver 54 operator fun Config.invoke(block: Config.() -> Unit) { block.invoke(this) }
  • 55.
    Functions 55 fun add(x: Int):(Int) -> Int { return fun(y: Int): Int { return x + y } } val result = add(10)(30)
  • 56.
    Functions 56 fun add(x: Int):(Int) -> Int { return { y: Int -> x + y } } val addFunc = add(10) val result = addFunc(30)
  • 57.
    Functions 57 fun add(x: Int):(Int) -> Int { return { x + it } } val addFunc = add(10) val result = addFunc(30)
  • 58.
    Functions 58 fun <T> map(x:String, op: (String) -> T): T { return op(x) } // used as map("John Smith", fun(n: String): Int { return n.length })
  • 59.
    Functions 59 fun <T> map(x:String, op: (String) -> T): T { return op(x) } // used as map("John Smith", { it.length })
  • 60.
    Functions 60 fun <T> map(x:String, op: (String) -> T): T { return op(x) } // used as map("John Smith") { it.length }
  • 61.
    Functions 61 fun <E> List<E>.test(op:(e: E) -> Boolean): List<E> { val ret = arrayListOf<E>() for (element in this) { if (op(element)) ret += element } return ret } // used as employees.test { it.age > 25 }
  • 62.
    Functions ● fold isone of most important functional operators 62 fun <T, R> Collection<T>.fold( initial: R, combine: (acc: R, nextElement: T) -> R ): R { var accumulator: R = initial for (element: T in this) { accumulator = combine(accumulator, element) } return accumulator }
  • 63.
    fold (a.k.a reduce):how it works 63source: http://perugini.cps.udayton.edu/teaching/books/PL/www/lecture_notes/currying.html
  • 64.
  • 65.
    Collections 65 val numbers =mutableListOf("one", "two", "three", "four") numbers += "five" val immutableNumbers = listOf("one", "two", "three", "four") immutableNumbers += "five" // compilation error
  • 66.
    Collection Operations ● Transformations ○Mapping (map) ○ Zipping (zip) ○ Flattening (flatmap) ● Filtering ○ Filtering (filter) ○ Partitioning (partition) ○ Testing predicates (any, none, all) ● Plus and Minus 66
  • 67.
    Collection Operations ● Grouping ○Group By (groupBy) ● Retrieving Collection Parts ○ Take and drop (takeWhile, dropWhile, takeLast, dropLast, take(n), drop(n)) ○ Partitioning (partition) ○ Testing predicates (any, none, all) ● Retrieve: ○ At index: (elementAt, []) ○ By condition: (first, last, find, findLast) 67
  • 68.
    Collection Operations ● Order: ○Sorting: (sortBy, sortedByDescending, reversed, shuffled) ● Aggregate: ○ Built-in: min, max, average, sum, count, maxBy, minBy ○ Custom: reduce, fold 68
  • 69.
    So, How tostart? 69
  • 70.
    Write your testcases in Kotlin 70 @Test fun `Test getContentType for image pdf byte stream`() { val pdfBytes = byteArrayOf(0x25, 0x50, 0x44, 0x46, 0x2d, 0x31, 0x2e, 0x34) // %PDF-1.4 val contentType = StreamUtil. getContentType(ByteArrayInputStream(pngPdfBytes), "abc.png") //give invalid name assertThat(contentType).isEqualTo("application/pdf") }
  • 71.
    Test Spring Apps 71 @Test fun`test calling translateToCategories will calculate the agent category correctly`() { // setup val agentRepository = mock(AgentRepository::class.java) val agentCategoryRepository = mock(AgentCategoryRepository::class.java) whenever(agentRepository.findAllById(any())) .thenReturn(listOf(createAgentOfExperience(10), createAgentOfExperience(5))) whenever(agentCategoryRepository.findAll()).thenReturn(dbLookup()) val carrierService = CarrierService(agentRepository, agentCategoryRepository) // SUT // when val translatedList: List<Long> = carrierService.translateToCategories() // then assertThat(translatedList).asList().containsExactlyInAnyOrder(CAT_5, CAT_6) }
  • 72.
  • 73.
    ● https://github.com/mhewedy/eureka-klient (pureKotlin app) ● https://gitlab.com/ticketz/ticketz-api (Kotlin + spring boot) ● https://github.com/mhewedy/condition-engine (Kotlin + java + spring boot) 73
  • 74.
  • 75.
    1. Strong vsWeak types 75 // Kotlin (strong typed) fun main() { val x: Float = 10.5f val y: Int = x // compilation error println("y = $y") } // C (weak typed) #include <stdio.h> int main() { float x = 10.5; int y = x; printf("y = %dn", y); // prints 10 }
  • 76.
  • 77.
    Resources ● https://www.wikiwand.com/en/Kotlin_(programming_language) ● https://kotlinlang.org/docs/reference/(very good resource) ● http://shop.oreilly.com/product/0636920052982.do ● http://shop.oreilly.com/product/0636920052999.do ● https://www.manning.com/books/kotlin-in-action ● https://medium.com/sngular-devs/from-closures-to-curry-and-compose-197d2abcadd8 77
  • 78.

Editor's Notes

  • #28 Iterate over Int by adding iterator() function and then implement next and hasNext for the iterator object (which is the int object in this case as now int is an iterator)
  • #48 Var args and spread operator
  • #49 Default args
  • #50 Default args
  • #51 infix
  • #52 Functions inside functions
  • #54 Operator overloading (invoke operator)
  • #55 Operator overloading (invoke operator)
  • #56 currying
  • #58 Currying and partial function
  • #59 When last parameter is a function
  • #60 When last parameter is a function
  • #61 When last parameter is a function
  • #62 When last parameter is a function: real world example