Slide 1

Slide 1 text

Kotlin Discovery 1

Slide 2

Slide 2 text

Moncef AOUDIA Consultant Zenika @AoudiaMoncef 2

Slide 3

Slide 3 text

Plan 1. Kotlin 2. The good 3. The bad 4. Android Kotlin 5. Spring Kotlin 6. Questions 3

Slide 4

Slide 4 text

Kotlin 4

Slide 5

Slide 5 text

Kotlin 5 Programing language for JVM Browser Android Native

Slide 6

Slide 6 text

Kotlin 6 Why Kotlin ? Concise Safe Interoperable Tool-friendly

Slide 7

Slide 7 text

The good 7

Slide 8

Slide 8 text

Null safety 8 var x: String = "hello" x = null // Null can not be a value of a non-null type String val x = "Hello" val y: String? = null println(x.length) // print 5 println(y?.length) // print null var y: String? = "world" y = null // ok, no error print(y) // print null

Slide 9

Slide 9 text

Extensions functions 9 fun Int.isEvenOrOdd() { if (this % 2 == 0) println("$this is even") else println("$this is odd") } fun main() { val num:Int? = 10 num?.isEvenOrOdd() }

Slide 10

Slide 10 text

Higher-order function 10 fun Collection.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 } val items = listOf(1, 2, 3, 4, 5) items.fold(0, { acc: Int, i: Int -> print("acc = $acc, i = $i, ") val result = acc + i println("result = $result") result })

Slide 11

Slide 11 text

Higher-order function 11 // Parameter types in a lambda are optional if they can be inferred: val joinedToString = items.fold("Elements:", { acc, i -> acc + " " + i }) // Function references can also be used for higher-order function calls: val product = items.fold(1, Int::times)

Slide 12

Slide 12 text

Sealed class 12 sealed class Opt { class Add(val value: Int) : Opt() class Sub(val value: Int) : Opt() class Mult(val value: Int) : Opt() class Div(val value: Int) : Opt() object Inc(val value: Int) : Opt() object Dec(val value: Int) : Opt() } fun calc(x: Int, op: Opt) = when (op) { is Opt.Add -> x + op.value is Opt.Sub -> x - op.value is Opt.Mult -> x * op.value is Opt.Div -> x / op.value Opt.Inc -> x + 1 Opt.Dec -> x - 1 // the `else` clause is not required because we've covered all the cases }

Slide 13

Slide 13 text

Scoping functions 13 Let, Apply, Also, With and Run

Slide 14

Slide 14 text

Let 14 /** * Calls the specified function [block] with `this` value as its argument and returns its result. */ public inline fun T.let(block: (T) -> R): R = block(this) val x = "Hello" val y = "World" val sb = StringBuilder() val letResult = sb.let{ it.append(x) it.append(y) "Let" } println(sb.toString()) //HelloWorld println(letResult) //Let val x = "Hello" val y = "World" var sb: StringBuilder? = null val letResult = sb?.let{ it.append(x) it.append(y) "Let" } println(letResult) //null sb = StringBuilder() sb.append(x) println(sb.toString()) //Hello

Slide 15

Slide 15 text

Apply 15 /** * Calls the specified function [block] with `this` value as its receiver and returns `this` value. */ public inline fun T.apply(block: T.() -> Unit): T { block(); return this } val lille = City() lille.name = "Lille" lille.surface = 3_951 lille.population = 233_897 val lille = City().apply { name = "Lille" surface = 3_951 population = 233_897 }

Slide 16

Slide 16 text

Also 16 /** * Calls the specified function [block] with `this` value as its argument and returns `this` value. */ @SinceKotlin("1.1") public inline fun T.also(block: (T) -> Unit): T { block(this); return this } // transforming data from database with intermediary variable val user = db.getUser(id = 0) log.debug(user.toString()) user.map { /** other stuff */ } // use 'also' to stay in the method chains val user = db.getUser(id = 0) .also { log.debug(it.toString())} .map { /** other stuff */ }

Slide 17

Slide 17 text

With 17 /** * Calls the specified function [block] with the given [receiver] as its receiver and returns its result. */ public inline fun with(receiver: T, block: T.() -> R): R = receiver.block() // using old way val surface = lille.surface val population = lille.population val density = population/surface // using 'with' to avoid repetitive references to identifier val density = with(lille) { population/surface }

Slide 18

Slide 18 text

Run 18 /** * Calls the specified function [block] with `this` value as its receiver and returns its result. */ public inline fun T.run(block: T.() -> R): R = block() /** * Calls the specified function block and returns its result. */ public inline fun run(block: () -> R): R = block() val person: Person = Person(...) val personRepository: PersonRepository = personRepository() personRepository.delete(person) fun printName(person: Person) = person.run { println(person.name) } val isDeleted: Boolean = run { val person: Person = Person(...) val personRepository: PersonRepository = personRepository() personRepository.delete(person) } fun printName(person: Person) = person.run { println(name) }

Slide 19

Slide 19 text

Scoping functions 19

Slide 20

Slide 20 text

Coroutines 20 // Create a custom CoroutineScope override val coroutineContext: CoroutineContext get() = Dispatchers.Main + job private lateinit var job: Job job = Job() launch(Dispatchers.Main) { // Suspend the execution of Coroutine until doLogin finish val user = withContext(Dispatchers.IO) { userService.doLogin(username, password) } // Get currentFriends without suspending the Coroutine val currentFriends = async(Dispatchers.IO) { userService.requestCurrentFriends(user) } // Get suggestedFriends without suspending the Coroutine val suggestedFriends = async(Dispatchers.IO) { userService.requestSuggestedFriends(user) } val finalUser = user.copy(friends = currentFriends.await() + suggestedFriends.await()) } // Wait for the execution of the Job job.join() job.cancel()

Slide 21

Slide 21 text

The bad 21

Slide 22

Slide 22 text

Heritage 22 class MyClass { } class SubClass : MyClass { /* /* this type is final, so it can be inherited from */ } open class MyClass { } class SubClass : MyClass { /* it works */ }

Slide 23

Slide 23 text

Data class 23 data class MyDataClass(val p: Int = 19) { } class SubClass : MyDataClass(p) { /* this type is final, so it can be inherited from */ } open class MyClass(val x: Int = 19) { } data class MyDataClass(val y: Int) : MyClass() { /* it works */ }

Slide 24

Slide 24 text

Class constructor 24 // primary constructor class PersonA(val firstName: String, val lastName: String) { } // regular constructor class PersonB { val firstName: String val lastName: String constructor(firstName: String, lastName: String){ this.firstName = firstName this.lastName = lastName } } class Student(val firstName: String, val lastName: String, val studentId: String) : Person(firstName,lastName) { }

Slide 25

Slide 25 text

Class companion 25 class MyClass { companion object { @JvmStatic fun myStaticMethod(/*...*/) { /*...*/ } } }

Slide 26

Slide 26 text

Type conversion 26 val x: Int = 19 val y: Long = x // Type mismatch: inferred type is Int but Long was expected fun main() { val x: Int = 128 val y: Byte = x.toByte() val z: Int = y.toInt() print("(x = $x, y = $y, z = $z)") } Output:(x = 128, y = -128, z = -128) val x: Int = 19 val y: Long = x.toLong() // Ok

Slide 27

Slide 27 text

Keywords 27 Hard Keywords Soft Keywords Modifier Keywords Other Keywords package, as, typealias, class, this, super, val, var, fun, for, null, true, false, is, in, throw, return, break, continue, object, if, try, else, while, do, when, interface, yield, typeof by, catch, constructor delegate, dynamic, field, file, finally, get, import, init, param, property, receiver, set setparam, where actual, abstract, annotation, companion, const, crossinline, data, enum, expect, external, final, infix, inline, inner, internal, lateinit, noinline, open, operator, out, override, private, protected, public, field, it, +, -, *, /, %, =, +=, -=, *=, /=, %=, ++, --, &&, ||, ! - , and, or, not, ==, !=, ===, !==, <, >, <=, >=, [, ], !!, ?., ?:, ::, .., :, ?, ->, @, ;, $, _

Slide 28

Slide 28 text

28

Slide 29

Slide 29 text

Kotlin Android It makes Android development much easier It’s seamlessly integrated with Android Studio If you’re an Android developer, you need to recycle There are well-known companies that already use it in production Companies are starting to ask for it on their job offers 29

Slide 30

Slide 30 text

Gradle Kotlin DSL 30 import org.jetbrains.kotlin.config.KotlinCompilerVersion plugins { id("com.android.application") id("kotlin-android") } android { compileSdkVersion(28) buildToolsVersion = "28.0.1" defaultConfig { applicationId = "com.zenika.bbl" ... } ... } dependencies { implementation(kotlin("stdlib-jdk7", KotlinCompilerVersion.VERSION)) testImplementation("junit:junit:4.12") }

Slide 31

Slide 31 text

Kotlin Android Extensions 31 // Using R.layout.activity_main from the 'main' source set import kotlinx.android.synthetic.main.activity_main.* class MyActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Instead of findViewById(R.id.textView) textView.setText("Hello, world!") } }

Slide 32

Slide 32 text

Android KTX 32 supportFragmentManager .beginTransaction() .replace(R.id.my_fragment_container, myFragment, FRAGMENT_TAG) .commitAllowingStateLoss() supportFragmentManager.transaction(allowStateLoss = true) { replace(R.id.my_fragment_container, myFragment, FRAGMENT_TAG) }

Slide 33

Slide 33 text

33

Slide 34

Slide 34 text

Kofu DSL 34 val app = webApplication { beans { bean() bean() } server { port = if (profiles.contains("test")) 8181 else 8080 router { val handler = ref() GET("/", handler::hello) GET("/api", handler::json) } codecs { string() jackson() } } }

Slide 35

Slide 35 text

Kofu DSL 35 data class Sample(val message: String) class SampleService { fun generateMessage() = "Hello world!" } class SampleHandler(private val sampleService: SampleService) { fun hello(request: ServerRequest)= ok().syncBody(sampleService.generateMessage()) fun json(request: ServerRequest) = ok().syncBody(Sample(sampleService.generateMessage())) } fun main() { app.run() }

Slide 36

Slide 36 text

Kotlin Script Templates 36 import io.spring.demo.* """ ${include("header")}

${i18n("title")}

    ${users.joinToLine{ "
  • ${i18n("user")} ${it.firstname} ${it.lastname}
  • " }}
${include("footer")} """

Slide 37

Slide 37 text

Demo 37

Slide 38

Slide 38 text

Questions 38

Slide 39

Slide 39 text

Sources ● https://antonioleiva.com/reasons-kotlin-android/ ● https://techbeacon.com/why-you-should-use-kotlin-android-development ● https://dzone.com/articles/why-kotlin-is-the-future-of-android-app-developmen ● https://developer.android.com/kotlin/faq ● https://dzone.com/articles/what-are-the-biggest-advantages-of-kotlin-over-jav ● https://hackernoon.com/why-we-choose-kotlin-for-creating-android-apps-46030b10d19c ● https://code.tutsplus.com/articles/java-vs-kotlin-should-you-be-using-kotlin-for-android-development--cm s-27846 ● https://github.com/MindorksOpenSource/from-java-to-kotlin ● https://codelabs.developers.google.com/codelabs/kotlin-coroutines/ ● https://dev.to/martinhaeusler/kotlin---the-good-the-bad-and-the-ugly-3jfo ● https://kukuruku.co/post/why-kotlin-sucks/ ● https://allegro.tech/2018/05/From-Java-to-Kotlin-and-Back-Again.html ● https://blog.dripstat.com/kotlin-in-production-the-good-the-bad-and-the-ugly-2/ 39

Slide 40

Slide 40 text

Sources ● https://kotlinlang.org/ ● https://proandroiddev.com/the-tldr-on-kotlins-let-apply-also-with-and-run-functions-6253f06d152b ● https://medium.com/@elye.project/mastering-kotlin-standard-functions-run-with-let-also-and-apply-9cd33 4b0ef84 ● https://antonioleiva.com/coroutines/ ● https://spring.io/blog/2017/01/04/introducing-kotlin-support-in-spring-framework-5-0 ● https://romannurik.github.io/SlidesCodeHighlighter/ ● http://kotlinlang.org/docs/reference/keyword-reference.html ● https://proandroiddev.com/kotlin-sealed-classes-enums-with-swag-d3c4b799bcd4 ● https://antonioleiva.com/sealed-classes-kotlin/ ● https://proandroiddev.com/migrating-android-app-to-gradle-kotlin-dsl-1-0-c903760275a5 ● https://github.com/spring-projects/spring-fu 40

Slide 41

Slide 41 text

Moncef AOUDIA Consultant Zenika @AoudiaMoncef 41