Kotlin 1.4 Language Features Svetlana Isakova October 12, 2020 - - PowerPoint PPT Presentation

kotlin 1 4 language features svetlana isakova
SMART_READER_LITE
LIVE PREVIEW

Kotlin 1.4 Language Features Svetlana Isakova October 12, 2020 - - PowerPoint PPT Presentation

Kotlin 1.4 Online Event Kotlin 1.4 Language Features Svetlana Isakova October 12, 2020 @sveta_isakova Kotlin 1.4 Language Features SAM conversions for Kotlin classes Explicit API mode Trailing comma Break and continue


slide-1
SLIDE 1

Kotlin 1.4 Online Event October 12, 2020 @sveta_isakova

Kotlin 1.4 Language Features Svetlana Isakova

slide-2
SLIDE 2

Kotlin 1.4 Language Features

  • SAM conversions for Kotlin classes
  • Explicit API mode
  • Trailing comma
  • Break and continue inside when expressions
  • Mixing named and positional arguments
  • New type inference
  • Unified exception type for null checks
slide-3
SLIDE 3

SAM conversions for Kotlin interfaces

slide-4
SLIDE 4

SAM = Single abstract method

interface Action { fun run() }

slide-5
SLIDE 5

SAM conversion

Ability to pass a lambda or callable reference when a SAM interface is expected

slide-6
SLIDE 6

runAction { println("I'm Kotlin 1.3") }

SAM conversion for a Java interface

public interface Action { void run(); } public static void runAction(Action action) { action.run(); }

Java: Kotlin:

slide-7
SLIDE 7

runAction { println("I'm Kotlin 1.3") }

SAM conversion for a Kotlin interface

interface Action { fun run() } fun runAction(a: Action) = a.run()

Java: Kotlin: Kotlin: Doesn’t work. Please use function types!

slide-8
SLIDE 8

KT-7770 SAM for Kotlin classes

SAM conversion only works for Java interfaces That’s by design: everyone should use functional types But that is inconvenient!

211 50+comments

slide-9
SLIDE 9

fun interface Action { fun run() }

Functional interfaces

slide-10
SLIDE 10

fun interface Action { fun run() } fun runAction(a: Action) = a.run() runAction { println("Hello, Kotlin 1.4!") }

Functional interfaces

slide-11
SLIDE 11

fun interface Action { fun run() fun runWithDelay() }

Why functional interfaces?

No longer a SAM interface!

Fun interfaces must have exactly one abstract method

slide-12
SLIDE 12

Explicit API mode

slide-13
SLIDE 13

Kotlin style guide

kotlinlang.org Ability to pass a lambda or callable reference when a SAM interface is expected

slide-14
SLIDE 14

Specify member visibility

fun privateFun() { … }

It’s PUBLIC! to avoid accidentally exposing declarations as public APIs

slide-15
SLIDE 15

Specify member visibility

private fun privateFun() { … } public fun publicFun() { … }

to avoid accidentally exposing declarations as public APIs

slide-16
SLIDE 16

Explicitly specify function return types and property types

fun getAnswer(finished: Boolean) = if (finished) "42" else "unknown" : String

to avoid accidentally changing the return type when the implementation changes

slide-17
SLIDE 17

Explicitly specify function return types and property types

to avoid accidentally changing the return type when the implementation changes

: Any fun getAnswer(finished: Boolean) = if (finished) 42 else "unknown"

slide-18
SLIDE 18

fun getAnswer(finished: Boolean) = if (finished) 42 else "unknown"

Explicit API mode

The visibility must be specified in explicit API mode The return type must be specified in explicit API mode

slide-19
SLIDE 19

public fun getAnswer(finished: Boolean): Any = if (finished) 42 else "unknown"

Explicit API mode

slide-20
SLIDE 20

Strict mode: reports errors

kotlin { explicitApi() } kotlin { explicitApi = 'strict' }

build.gradle: build.gradle.kts:

slide-21
SLIDE 21

Warning mode: reports warnings

kotlin { explicitApiWarning() } kotlin { explicitApi = 'warning' }

build.gradle: build.gradle.kts:

slide-22
SLIDE 22

Trailing comma

slide-23
SLIDE 23

Argument list

val colors = listOf( "red", "green", "blue" )

slide-24
SLIDE 24

Argument list

val colors = listOf( "red", "blue" "green", )

Compiler error: Expecting ','

slide-25
SLIDE 25

Argument list

val colors = listOf( "red", "green", "blue", )

slide-26
SLIDE 26

Argument list

val colors = listOf( "red", "green", "blue", )

slide-27
SLIDE 27

Argument list

val colors = listOf( "red", "blue", "green", )

slide-28
SLIDE 28

Function declaration

fun displayRectangle( color: Color, width: Int, height: Int, ) { ../ }

slide-29
SLIDE 29

Class declaration

data class Contact( val address: String, val phoneNumber: String, val email: String, )

slide-30
SLIDE 30

Break & continue in when expressions

slide-31
SLIDE 31

Kotlin 1.3 forbids break and continue in when expressions

fun foo(list: List<Int>) { for (i in list) { when (i) { 42 -? continue else -? println(i) } } }

'break' and 'continue' are not allowed in 'when' statements. Consider using labels to continue/break from the outer loop.

slide-32
SLIDE 32

Workaround: using labels

fun foo(list: List<Int>) { l@ for (i in list) { when (i) { 42 -? continue@l else -? println(i) } } }

slide-33
SLIDE 33

Kotlin 1.4 allows break and continue in when expressions

fun foo(list: List<Int>) { for (i in list) { when (i) { 42 -? continue else -? println(i) } } }

slide-34
SLIDE 34

Kotlin 1.4 allows break and continue in when expressions

fun foo(list: List<Int>) { for (i in list) { when (i) { 42 -? break else -? println(i) } } }

slide-35
SLIDE 35

Mixing named and positional arguments

slide-36
SLIDE 36

Kotlin 1.3: using named args

drawRectangle( width = 10, height = 20, color = Color.BLUE )

redundant helpful helpful

slide-37
SLIDE 37

Kotlin 1.3: mixing not allowed

drawRectangle( width = 10, height = 20, Color.BLUE )

Mixing named and positioned arguments is not allowed.

slide-38
SLIDE 38

Kotlin 1.4

drawRectangle( width = 10, height = 20, color = Color.BLUE )

slide-39
SLIDE 39

New Type Inference

slide-40
SLIDE 40

New Type Inference

  • Infers types automatically in more use-cases
  • Supports smart casts in more complicated scenarios
  • Supports more cases for using callable references
  • And much more
slide-41
SLIDE 41

Kotlin 1.3: lambda parameter type

val rulesMap: Map<String, (String?) -? Boolean> = mapOf( "weak" to { it !> null }, "medium" to { !it.isNullOrBlank() }, "strong" to { it !> null &' "^[a-zA-Z0-9]+$".toRegex().matches(it) } )

slide-42
SLIDE 42

Kotlin 1.3: lambda parameter type

val rulesMap: Map<String, (String?) -? Boolean> = mapOf( "weak" to { it !> null }, "medium" to { !it.isNullOrBlank() }, "strong" to { it !> null &' "^[a-zA-Z0-9]+$".toRegex().matches(it) } )

slide-43
SLIDE 43

Kotlin 1.3: lambda parameter type

val rulesMap: Map<String, (String?) -? Boolean> = mapOf( "weak" to { it !> null }, "medium" to { !it.isNullOrBlank() }, "strong" to { it !> null &' "^[a-zA-Z0-9]+$".toRegex().matches(it) } )

slide-44
SLIDE 44

Kotlin 1.3: lambda parameter type

val rulesMap: Map<String, (String?) -? Boolean> = mapOf( "weak" to { it !> null }, "medium" to { !it.isNullOrBlank() }, "strong" to { it !> null &' "^[a-zA-Z0-9]+$".toRegex().matches(it) } )

: String?

slide-45
SLIDE 45

Kotlin 1.4: lambda parameter type

val rulesMap: Map<String, (String?) -? Boolean> = mapOf( "weak" to { it !> null }, "medium" to { !it.isNullOrBlank() }, "strong" to { it !> null &' "^[a-zA-Z0-9]+$".toRegex().matches(it) } )

slide-46
SLIDE 46

Kotlin 1.3: lambda’s last expression

val result = run { var str = currentValue() if (str => null) { str = "test" } str } :String?

slide-47
SLIDE 47

Kotlin 1.4: lambda’s last expression

val result = run { var str = currentValue() if (str => null) { str = "test" } str } :String?

slide-48
SLIDE 48

References to functions with default argument values

fun foo(i: Int = 0): String = "$i!" apply(:;foo) :(Int)-?String

slide-49
SLIDE 49

References to functions with default argument values

fun foo(i: Int = 0): String = "$i!" apply(:;foo) :()-?String

slide-50
SLIDE 50

References to functions with default argument values

fun foo(i: Int = 0): String = "$i!" apply(:;foo) /0 0! fun apply(f: () -? String): String = f()

slide-51
SLIDE 51

Unified exception type for null checks

slide-52
SLIDE 52

Unified exception type

IllegalStateException TypeCastException IllegalArgumentException KotlinNullPointerException

!!, as Type, platform-typed expression null checks, parameter null checks

NullPointerException

slide-53
SLIDE 53

The message remains the same

  • Kotlin 1.3:

IllegalStateException: User.name must not be null

  • Kotlin 1.4:

NullPointerException: User.name must not be null

slide-54
SLIDE 54

This makes future optimizations possible

  • Optimizations by the Kotlin compiler
  • Optimizations by various kinds
  • f bytecode processing tools,

such as the Android R8 optimizer

slide-55
SLIDE 55

Generating default methods in interfaces (experimental)

slide-56
SLIDE 56

Default methods in interfaces

Works with the Java 6 target!

interface Alien { fun speak() = "Wubba lubba dub dub" } class BirdPerson : Alien

slide-57
SLIDE 57

Under the hood: DefaultImpls

public interface Alien { String speak(); public static final class DefaultImpls { public static String speak(Alien obj) { return "Wubba lubba dub dub"; } } }

slide-58
SLIDE 58

public final class BirdPerson implements Alien { public String speak() { return Alien.DefaultImpls.speak(this); } }

Under the hood: DefaultImpls

slide-59
SLIDE 59

Default methods in Kotlin 1.2+

interface Alien { @JvmDefault fun speak() = "Wubba lubba dub dub" }

  • Xjvm-default=enable

No DefaultImpls is generated!

slide-60
SLIDE 60

Generating default methods in Kotlin 1.2+

  • Use one of the special modes for the Java 8 target:
  • Generating only default methods
  • Generating default methods and DefaultImpls

classes for compatibility

  • Annotate with @JvmDefault each interface method

that has an implementation

slide-61
SLIDE 61

Generating default methods in Kotlin 1.4

  • Use one of the new modes for the Java 8 target:
  • Generating only default methods
  • Generating default methods and DefaultImpls

classes for compatibility

  • Annotate with @JvmDefault each interface method

that has an implementation

slide-62
SLIDE 62

Generating default methods in Kotlin 1.4

  • Use one of the new modes for the Java 8 target:
  • Generating only default methods
  • Generating default methods and DefaultImpls

classes for compatibility

slide-63
SLIDE 63

Default methods in Kotlin 1.4

interface Alien { fun speak() = "Wubba lubba dub dub" }

  • Xjvm-default=all

No DefaultImpls is generated! No @JvmDefault annotation is needed!

slide-64
SLIDE 64

New modes

  • Currently experimental
  • Will be used by default in the future major versions:
  • Xjvm-default=all-compatibility
  • Xjvm-default=all
slide-65
SLIDE 65

New modes

  • Currently experimental
  • Will be used by default in the future major versions:
  • Xjvm-default=all-compatibility
  • Xjvm-default=all
slide-66
SLIDE 66

More resources

slide-67
SLIDE 67

Read more at the Kotlin blog

slide-68
SLIDE 68

What’s New in 1.4 documentation page

slide-69
SLIDE 69

Thanks! Have a nice Kotlin

@sveta_isakova