Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo
Svetlana Isakova
Why Kotlin?
- modern
- pragmatic
Kotlin Programming
Language
Kotlin developers
0
750
1500
2250
3000
2016 2017 2018
156K
700K
2.2M
Timeline
… …
2017 Official on Android
2010 Project started
2016 Kotlin 1.0
2018 Kotlin 1.3
Programming language for:
Pragmatic
- good tooling
- good Java
interoperability
From
has good tooling
- completion
- navigation
- refactorings
- inspections
…
can be easily mixed with
Java code
Kotlin code
Java code
You can have Java &
Kotlin code in one project
You can gradually add Kotlin to
your existing app
Modern
- concise
- safe
- expressive
concise & readable
public class Person {

private final String name;

private final int age;



public Person(String name, int age) {

this.name = name;

this.age = age;

}



public String getName() {

return name;

}



public int getAge() {

return age;

}

}
- equals
- hashCode
- toString


data


class Person(val name: String, val age: Int)
public void updateWeather(int degrees) {

String description;

Colour colour;

if (degrees < 5) {

description = "cold";

colour = BLUE;

} else if (degrees < 23) {

description = "mild";

colour = ORANGE;

} else {

description = "hot";

colour = RED;

}

// ...

}
enum Colour { BLUE, ORANGE, RED, /*...*/; }
fun updateWeather(degrees: Int) {

val description: String

val colour: Colour

if (degrees < 5) {

description = "cold"

colour = BLUE

} else if (degrees < 23) {

description = "mild"

colour = ORANGE

} else {

description = "hot"

colour = RED

}

// ...

}
fun updateWeather(degrees: Int) {

val (description: String, colour: Colour) =

if (degrees < 5) {

Pair("cold", BLUE)

} else if (degrees < 23) {

Pair("mild", ORANGE)

} else {

Pair("hot", RED)

}
// ...

}
fun updateWeather(degrees: Int) {

val (description, colour) =

if (degrees < 5) {

Pair("cold", BLUE)

} else if (degrees < 23) {

Pair("mild", ORANGE)

} else {

Pair("hot", RED)

}
// ...

}
fun updateWeather(degrees: Int) {

val (description, colour) = when {

degrees < 5 -> Pair("cold", BLUE)

degrees < 23 -> Pair("mild", ORANGE)

else -> Pair("hot", RED)

}
// ...

}
val (description, colour) = when {

degrees < 5 -> Pair("cold", BLUE)

degrees < 23 -> Pair("mild", ORANGE)

else -> Pair("hot" to RED)

}
String description;

Colour colour;
if (degrees < 5) {

description = "cold";

colour = BLUE;

} else if (degrees < 23) {

description = "mild";

colour = ORANGE;

} else {

description = "hot";

colour = RED;

}
safe
Billion Dollar Mistake
Modern approach:
to make NPE
compile-time error,
not run-time error
Nullable types in Kotlin
val s1: String = "always not null"


val s2: String? = null
s1.length ✓
✗s2.length
"can be null or non-null"
null ✗
val s: String?
if (s != null) {

s.length

}
Dealing with Nullable Types
s?.length
val s: String?
Dealing with Nullable Types
val length = if (s != null) s.length else null
val s: String?
Nullability operators
val length = s?.length
val length = if (s != null) s.length else null
val s: String?
Nullability operators
val length: Int? = s?.length
val length = if (s != null) s.length else 0
val s: String?
Nullability operators
val length: Int = s?.length ?: 0
val s: String?
Making NPE explicit
s!!
throws NPE if s is null
s!!.length
Nullable Types Under the Hood
No performance overhead
@Nullable, @NotNull annotations
class Optional<T>(val value: T) {


fun isPresent() = value != null



fun get() = value ?:

throw NoSuchElementException("No value present")
}
Nullable types ≠ Optional
Using annotated Java types from Kotlin
Type
behaves like
regular Java type
@ParametersAreNonnullByDefault
@Nullable
@NotNull Type
Type?
Type
Type
@MyNonnullApi
Type/
Type?
expressive
more code reuse!
expressive
you can avoid any repetition
you can make the code look nicer
you can create API looking like DSL
expressive
Extension Functions
Extension Functions
val c: Char = "abc".lastChar()
fun String.lastChar() = get(length - 1)
fun String.lastChar() = get(length - 1)
this can be omitted
Extension Functions
fun String.lastChar() = this.get(this.length - 1)
fun String.lastChar() = get(length - 1)
Calling Extension Functions
from Java code
StringExtensions.kt
char c = StringExtensionsKt.lastChar("abc");
JavaClass.java
import static StringExtensionsKt.lastChar;
char c = lastChar("abc");
No. Because it’s a regular
static method under the hood.
fun String.lastChar() = get(length - 1)
Extension Functions
Is it possible to call a private
member of String here?
Lambdas
Lambdas
button.addActionListener { println("Hi") }
{ employee: Employee -> employee.city == City.PRAGUE }
What’s an average
age of employees
working in Prague?
Working with collections with Lambdas
val employees: List<Employee>
employees.filter { it.city == City.PRAGUE }.map { it.age }.average()
data class Employee(
val city: City, val age: Int
)
What’s an average
age of employees
working in Prague?
Working with collections with Lambdas
val employees: List<Employee>
data class Employee(
val city: City, val age: Int
)
extension functions
employees.filter { it.city == City.PRAGUE }.map { it.age }.average()
Kotlin library: extensions on collections
• filter
• map
• reduce
• count
• find
• any
• flatMap
• groupBy
• …
Extension Function & Lambda
Lambda with receiver
val sb = StringBuilder()

with (sb) {

appendln("Alphabet: ")

for (c in 'a'..'z') {

append(c)

}
toString()

}
The with function
with is a function
val sb = StringBuilder()

sb.appendln("Alphabet: ")

for (c in 'a'..'z') {

sb.append(c)

}

sb.toString()

val sb = StringBuilder()

with (sb) {

this.appendln("Alphabet: ")

for (c in 'a'..'z') {

this.append(c)

}
this.toString()

}
val sb = StringBuilder()

with (sb, { ->

this.appendln("Alphabet: ")

for (c in 'a'..'z') {

this.append(c)

}
this.toString()

})
lambda
is its
second
argument
Lambda with receiverwith is a function
this is
an implicit receiver
in the lambda
val sb = StringBuilder()

with (sb) {

appendln("Alphabet: ")

for (c in 'a'..'z') {

append(c)

}
toString()

}
this can be omitted
Lambda with receiver
val sb = StringBuilder()

with (sb) {

appendln("Alphabet: ")

for (c in 'a'..'z') {

this.append(c)

}
}
lambda with
implicit this
Under the Hood
No performance overhead
Lambdas can be inlined
with (window) {
width = 300
height = 200
isVisible = true
}
The with function
class Window(
var width: Int,
var height: Int,
var isVisible: Boolean
)
window.width = 300
window.height = 200
window.isVisible = true
with (window) {
width = 300
height = 200
isVisible = true
}
Inline functions
is declared as
inline function
generated bytecode is similar to:
No performance overhead for creating a lambda!
The apply function
val mainWindow =
windowById["main"]?.apply {
width = 300
height = 200
isVisible = true
} ?: return
Applies the given actions
and returns receiver as a result:
DSLs
html {

table {

for (product in products) {

tr {

td { text(product.description) }

td { text(product.price) }

td { text(product.popularity) }

}

}

}

}
HTML Builders
lambdas with receiver
plugins {
application
kotlin("jvm") version "1.3.50"
}
application {
mainClassName = "samples.HelloWorldKt"
}
dependencies {
compile(kotlin("stdlib"))
}
repositories {
jcenter()
}
Gradle Build Script in Kotlin
router {
accept(TEXT_HTML).nest {
GET("/") { ok().render("index") }
GET("/sse") { ok().render("sse") }
GET("/users", userHandler::findAllView)
}
"/api".nest {
accept(APPLICATION_JSON).nest {
GET("/users", userHandler::findAll)
}
accept(TEXT_EVENT_STREAM).nest {
GET("/users", userHandler::stream)
}
}
resources("/**", ClassPathResource("static/"))
}
Kofu* (Kotlin + functional) DSL for Spring Boot
*part of Spring Fu
(an incubator for
new Spring features)
Multi-platform Projects
Multi-platform projects
Browser
Kotlin/JS
Android
Kotlin/JVM
iOS
Kotlin/Native
Server
Kotlin/JVM
common

code
Sharing common code
• Sharing business logic
• Keeping UI platform-dependent
• The shared part might vary
Common code
• you define expect declarations in the common
code and use them
• you provide different actual implementations
for different platforms
Time measurement example
expect fun measureTime(action: () -> Unit): Duration
Expected platform-specific API:
Expected API can be used in the common code:
measureTime {

// operation

}
Platform-specific Implementations
expect fun measureTime(action: () -> Unit): Duration
actual fun measureTime(action: () -> Unit): Duration {

// implementation using System.nanoTime()

}
actual fun measureTime(action: () -> Unit): Duration {

// implementation using window.performance.now()

}
actual fun measureTime(action: () -> Unit): Duration {

// implementation using std::chrono::high_resolution_clock

}
Kotlin/JVM
Kotlin/JS
Kotlin/Native
Common code
• can use the standard library
• can define expect declarations and use them
• can use other multi-platform libraries
Multi-platform libraries
• Standard library
• Ktor HTTP client
• kotlinx.serialization
• kotlinx.coroutines
• … and more
Many apps already in production
Going Native: How I used Kotlin Native to Port 6 years
of Android Game Code to iOS in 6 months
Shipping a Mobile Multiplatform Project on iOS &
Android
Your Multiplatform Kaptain has Arrived:  iOS release is
powered by Kotlin Multiplatform
play.kotlinlang.org
Introduction to kotlin
Kotlin course at Coursera
Have a nice Kotlin!

More Related Content

Introduction to kotlin

  • 2. - modern - pragmatic Kotlin Programming Language
  • 4. Timeline … … 2017 Official on Android 2010 Project started 2016 Kotlin 1.0 2018 Kotlin 1.3
  • 6. Pragmatic - good tooling - good Java interoperability
  • 9. - completion - navigation - refactorings - inspections …
  • 10. can be easily mixed with Java code
  • 11. Kotlin code Java code You can have Java & Kotlin code in one project
  • 12. You can gradually add Kotlin to your existing app
  • 15. public class Person {
 private final String name;
 private final int age;
 
 public Person(String name, int age) {
 this.name = name;
 this.age = age;
 }
 
 public String getName() {
 return name;
 }
 
 public int getAge() {
 return age;
 }
 }
  • 16. - equals - hashCode - toString 
 data 
 class Person(val name: String, val age: Int)
  • 17. public void updateWeather(int degrees) {
 String description;
 Colour colour;
 if (degrees < 5) {
 description = "cold";
 colour = BLUE;
 } else if (degrees < 23) {
 description = "mild";
 colour = ORANGE;
 } else {
 description = "hot";
 colour = RED;
 }
 // ...
 } enum Colour { BLUE, ORANGE, RED, /*...*/; }
  • 18. fun updateWeather(degrees: Int) {
 val description: String
 val colour: Colour
 if (degrees < 5) {
 description = "cold"
 colour = BLUE
 } else if (degrees < 23) {
 description = "mild"
 colour = ORANGE
 } else {
 description = "hot"
 colour = RED
 }
 // ...
 }
  • 19. fun updateWeather(degrees: Int) {
 val (description: String, colour: Colour) =
 if (degrees < 5) {
 Pair("cold", BLUE)
 } else if (degrees < 23) {
 Pair("mild", ORANGE)
 } else {
 Pair("hot", RED)
 } // ...
 }
  • 20. fun updateWeather(degrees: Int) {
 val (description, colour) =
 if (degrees < 5) {
 Pair("cold", BLUE)
 } else if (degrees < 23) {
 Pair("mild", ORANGE)
 } else {
 Pair("hot", RED)
 } // ...
 }
  • 21. fun updateWeather(degrees: Int) {
 val (description, colour) = when {
 degrees < 5 -> Pair("cold", BLUE)
 degrees < 23 -> Pair("mild", ORANGE)
 else -> Pair("hot", RED)
 } // ...
 }
  • 22. val (description, colour) = when {
 degrees < 5 -> Pair("cold", BLUE)
 degrees < 23 -> Pair("mild", ORANGE)
 else -> Pair("hot" to RED)
 } String description;
 Colour colour; if (degrees < 5) {
 description = "cold";
 colour = BLUE;
 } else if (degrees < 23) {
 description = "mild";
 colour = ORANGE;
 } else {
 description = "hot";
 colour = RED;
 }
  • 23. safe
  • 25. Modern approach: to make NPE compile-time error, not run-time error
  • 26. Nullable types in Kotlin val s1: String = "always not null" 
 val s2: String? = null s1.length ✓ ✗s2.length "can be null or non-null" null ✗
  • 27. val s: String? if (s != null) {
 s.length
 } Dealing with Nullable Types
  • 28. s?.length val s: String? Dealing with Nullable Types
  • 29. val length = if (s != null) s.length else null val s: String? Nullability operators val length = s?.length
  • 30. val length = if (s != null) s.length else null val s: String? Nullability operators val length: Int? = s?.length
  • 31. val length = if (s != null) s.length else 0 val s: String? Nullability operators val length: Int = s?.length ?: 0
  • 32. val s: String? Making NPE explicit s!! throws NPE if s is null s!!.length
  • 33. Nullable Types Under the Hood No performance overhead @Nullable, @NotNull annotations
  • 34. class Optional<T>(val value: T) { 
 fun isPresent() = value != null
 
 fun get() = value ?:
 throw NoSuchElementException("No value present") } Nullable types ≠ Optional
  • 35. Using annotated Java types from Kotlin Type behaves like regular Java type @ParametersAreNonnullByDefault @Nullable @NotNull Type Type? Type Type @MyNonnullApi Type/ Type?
  • 38. you can avoid any repetition you can make the code look nicer you can create API looking like DSL expressive
  • 40. Extension Functions val c: Char = "abc".lastChar() fun String.lastChar() = get(length - 1)
  • 41. fun String.lastChar() = get(length - 1) this can be omitted Extension Functions fun String.lastChar() = this.get(this.length - 1)
  • 42. fun String.lastChar() = get(length - 1) Calling Extension Functions from Java code StringExtensions.kt char c = StringExtensionsKt.lastChar("abc"); JavaClass.java import static StringExtensionsKt.lastChar; char c = lastChar("abc");
  • 43. No. Because it’s a regular static method under the hood. fun String.lastChar() = get(length - 1) Extension Functions Is it possible to call a private member of String here?
  • 46. { employee: Employee -> employee.city == City.PRAGUE } What’s an average age of employees working in Prague? Working with collections with Lambdas val employees: List<Employee> employees.filter { it.city == City.PRAGUE }.map { it.age }.average() data class Employee( val city: City, val age: Int )
  • 47. What’s an average age of employees working in Prague? Working with collections with Lambdas val employees: List<Employee> data class Employee( val city: City, val age: Int ) extension functions employees.filter { it.city == City.PRAGUE }.map { it.age }.average()
  • 48. Kotlin library: extensions on collections • filter • map • reduce • count • find • any • flatMap • groupBy • …
  • 49. Extension Function & Lambda Lambda with receiver
  • 50. val sb = StringBuilder()
 with (sb) {
 appendln("Alphabet: ")
 for (c in 'a'..'z') {
 append(c)
 } toString()
 } The with function with is a function val sb = StringBuilder()
 sb.appendln("Alphabet: ")
 for (c in 'a'..'z') {
 sb.append(c)
 }
 sb.toString()

  • 51. val sb = StringBuilder()
 with (sb) {
 this.appendln("Alphabet: ")
 for (c in 'a'..'z') {
 this.append(c)
 } this.toString()
 } val sb = StringBuilder()
 with (sb, { ->
 this.appendln("Alphabet: ")
 for (c in 'a'..'z') {
 this.append(c)
 } this.toString()
 }) lambda is its second argument Lambda with receiverwith is a function this is an implicit receiver in the lambda val sb = StringBuilder()
 with (sb) {
 appendln("Alphabet: ")
 for (c in 'a'..'z') {
 append(c)
 } toString()
 } this can be omitted
  • 52. Lambda with receiver val sb = StringBuilder()
 with (sb) {
 appendln("Alphabet: ")
 for (c in 'a'..'z') {
 this.append(c)
 } } lambda with implicit this
  • 53. Under the Hood No performance overhead Lambdas can be inlined
  • 54. with (window) { width = 300 height = 200 isVisible = true } The with function class Window( var width: Int, var height: Int, var isVisible: Boolean )
  • 55. window.width = 300 window.height = 200 window.isVisible = true with (window) { width = 300 height = 200 isVisible = true } Inline functions is declared as inline function generated bytecode is similar to: No performance overhead for creating a lambda!
  • 56. The apply function val mainWindow = windowById["main"]?.apply { width = 300 height = 200 isVisible = true } ?: return Applies the given actions and returns receiver as a result:
  • 57. DSLs
  • 58. html {
 table {
 for (product in products) {
 tr {
 td { text(product.description) }
 td { text(product.price) }
 td { text(product.popularity) }
 }
 }
 }
 } HTML Builders lambdas with receiver
  • 59. plugins { application kotlin("jvm") version "1.3.50" } application { mainClassName = "samples.HelloWorldKt" } dependencies { compile(kotlin("stdlib")) } repositories { jcenter() } Gradle Build Script in Kotlin
  • 60. router { accept(TEXT_HTML).nest { GET("/") { ok().render("index") } GET("/sse") { ok().render("sse") } GET("/users", userHandler::findAllView) } "/api".nest { accept(APPLICATION_JSON).nest { GET("/users", userHandler::findAll) } accept(TEXT_EVENT_STREAM).nest { GET("/users", userHandler::stream) } } resources("/**", ClassPathResource("static/")) } Kofu* (Kotlin + functional) DSL for Spring Boot *part of Spring Fu (an incubator for new Spring features)
  • 63. Sharing common code • Sharing business logic • Keeping UI platform-dependent • The shared part might vary
  • 64. Common code • you define expect declarations in the common code and use them • you provide different actual implementations for different platforms
  • 65. Time measurement example expect fun measureTime(action: () -> Unit): Duration Expected platform-specific API: Expected API can be used in the common code: measureTime { // operation }
  • 66. Platform-specific Implementations expect fun measureTime(action: () -> Unit): Duration actual fun measureTime(action: () -> Unit): Duration { // implementation using System.nanoTime() } actual fun measureTime(action: () -> Unit): Duration { // implementation using window.performance.now() } actual fun measureTime(action: () -> Unit): Duration { // implementation using std::chrono::high_resolution_clock } Kotlin/JVM Kotlin/JS Kotlin/Native
  • 67. Common code • can use the standard library • can define expect declarations and use them • can use other multi-platform libraries
  • 68. Multi-platform libraries • Standard library • Ktor HTTP client • kotlinx.serialization • kotlinx.coroutines • … and more
  • 69. Many apps already in production Going Native: How I used Kotlin Native to Port 6 years of Android Game Code to iOS in 6 months Shipping a Mobile Multiplatform Project on iOS & Android Your Multiplatform Kaptain has Arrived:  iOS release is powered by Kotlin Multiplatform
  • 72. Kotlin course at Coursera
  • 73. Have a nice Kotlin!