Table of Contents

Pathway 1: Kotlin fundamentals

My conspectus of:

https://developer.android.com/courses/pathways/android-basics-compose-unit-2-pathway-1

1. Kotlin Fundamentals

… Optional video …

2. Write conditionals in Kotlin

fun main() {
    val trafficLightColor = "Black"
 
    if (trafficLightColor == "Red") {
        println("Stop")
    } else if (trafficLightColor == "Yellow") {
        println("Slow")
    } else if (trafficLightColor == "Green") {
        println("Go")
    } else {
        println("Invalid traffic-light color")
    }
}
fun main() {
    val trafficLightColor = "Black"
 
    when (trafficLightColor) {
        "Red" -> println("Stop")
        "Yellow" -> println("Slow")
        "Green" -> println("Go")
        else -> println("Invalid traffic-light color")
    }
}
when {
    x.isOdd() -> print("x is odd")
    y.isEven() -> print("y is even")
    else -> print("x+y is odd")
}
when (x) {
    2, 3, 5, 7 -> println("x is a prime number between 1 and 10.")
    else -> println("x isn't a prime number between 1 and 10.")
}
when (x) {
    2, 3, 5, 7 -> println("x is a prime number between 1 and 10.")
    in 1..10 -> println("x is a number between 1 and 10, but not a prime number.")
    else -> println("x isn't a prime number between 1 and 10.")
}
when (x) {
    2, 3, 5, 7 -> println("x is a prime number between 1 and 10.")
    in 1..10 -> println("x is a number between 1 and 10, but not a prime number.")
    is Int -> println("x is an integer number, but not between 1 and 10.")
    else -> println("x isn't an integer number.")
}
fun main() {
    val trafficLightColor = "Black"
 
    val message = 
      if (trafficLightColor == "Red") "Stop"
      else if (trafficLightColor == "Yellow") "Slow"
      else if (trafficLightColor == "Green") "Go"
      else "Invalid traffic-light color"
 
    println(message)
}

3. Use nullability in Kotlin

fun main() {
    var favoriteActor: String? = null
    println(favoriteActor?.length) // => prints "null"
}
fun main() {
    var favoriteActor: String? = "Sandra Oh"
 
    val lengthOfName = if (favoriteActor != null) {
      favoriteActor.length
    } else {
      0
    }
 
    println("The number of characters in your favorite actor's name is $lengthOfName.")
}
fun main() {
    var favoriteActor: String? = "Sandra Oh"
    val lengthOfName = favoriteActor?.length ?: 0
    println("The number of characters in your favorite actor's name is $lengthOfName.")
}

4. Use classes and objects in Kotlin

1. Before you begin

2. Define a class

class SmartDevice {
    // empty body
}

3. Create an instance of a class

fun main() {
    val smartTvDevice = SmartDevice()
}

4. Define class methods

class SmartDevice {
    fun turnOn() {
        println("Smart device is turned on.")
    }
 
    fun turnOff() {
        println("Smart device is turned off.")
    }
}
 
fun main() {
    val smartTvDevice = SmartDevice()
    smartTvDevice.turnOn()
    smartTvDevice.turnOff()
}

5. Define class properties

var speakerVolume = 2
    get() = field  
    set(value) {
        field = value    
    }

6. Define a constructor

Default constructor

class SmartDevice constructor() {
    ...
}
class SmartDevice {
    ...
}

Parameterized constructor

class SmartDevice(val name: String, val category: String) {
 
    var deviceStatus = "online"
 
    fun turnOn() {
        println("Smart device is turned on.")
    }
 
    fun turnOff() {
        println("Smart device is turned off.")
    }
}
class SmartDevice(val name: String, val category: String) {
    var deviceStatus = "online"

    constructor(name: String, category: String, statusCode: Int) : this(name, category) {
        deviceStatus = when (statusCode) {
            0 -> "offline"
            1 -> "online"
            else -> "unknown"
        }
    }
    ...
}

7. Implement a relationship between classes

open class SmartDevice(val name: String, val category: String) {
    ...
}
class SmartTvDevice(deviceName: String, deviceCategory: String) :
    SmartDevice(name = deviceName, category = deviceCategory) {
}
class SmartTvDevice(deviceName: String, deviceCategory: String) :
    SmartDevice(name = deviceName, category = deviceCategory) {
 
// ...
 
    override fun turnOn() {
        deviceStatus = "on"
        println(
            "$name is turned on. Speaker volume is set to $speakerVolume and channel number is " +
                "set to $channelNumber."
        )
    }
 
    override fun turnOff() {
        deviceStatus = "off"
        println("$name turned off")
    }
}
class SmartLightDevice(deviceName: String, deviceCategory: String) :
    SmartDevice(name = deviceName, category = deviceCategory) {
 
// ...
 
    override fun turnOn() {
        super.turnOn()
        brightnessLevel = 2
        println("$name turned on. The brightness level is $brightnessLevel.")
    }
 
    override fun turnOff() {
        super.turnOff()
        brightnessLevel = 0
        println("Smart Light turned off")
    }
}
open class SmartDevice(val name: String, val category: String) {
 
    var deviceStatus = "online"
 
    open val deviceType = "unknown"
    ...
}
 
class SmartTvDevice(deviceName: String, deviceCategory: String) :
    SmartDevice(name = deviceName, category = deviceCategory) {
 
    override val deviceType = "Smart TV"
 
    ...
}
 
class SmartLightDevice(deviceName: String, deviceCategory: String) :
    SmartDevice(name = deviceName, category = deviceCategory) {
 
    override val deviceType = "Smart Light"
 
    ...
 
}

8. Visibility modifiers

open class SmartDevice protected constructor (val name: String, val category: String) {
    // ...
}
internal open class SmartDevice(val name: String, val category: String) {
    // ...
}

9. Define property delegates

class RangeRegulator(
    initialValue: Int,
    private val minValue: Int,
    private val maxValue: Int
) : ReadWriteProperty<Any?, Int> {

    var fieldData = initialValue

    override fun getValue(thisRef: Any?, property: KProperty<*>): Int {
        return fieldData
    }

    override fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) {
        if (value in minValue..maxValue) {
            fieldData = value
        }
    }
}

class SmartTvDevice(deviceName: String, deviceCategory: String) :
    SmartDevice(name = deviceName, category = deviceCategory) {

    override val deviceType = "Smart TV"

    private var speakerVolume by RangeRegulator(initialValue = 2, minValue = 0, maxValue = 100)

    private var channelNumber by RangeRegulator(initialValue = 1, minValue = 0, maxValue = 200)

    ...

}


class SmartLightDevice(deviceName: String, deviceCategory: String) :
    SmartDevice(name = deviceName, category = deviceCategory) {

    override val deviceType = "Smart Light"

    private var brightnessLevel by RangeRegulator(initialValue = 0, minValue = 0, maxValue = 100)

    ...

}

10. Test the solution

…

11. Try this challenge

…

12. Conclusion

Summary

5. Use function types and lambda expressions in Kotlin

1. Introduction

…

2. Watch the code-along video

…

3. Store a function in a variable

fun main() {
    val trickFunction = ::trick
}
 
fun trick() {
    println("No treats!")
}
fun main() {
    val trickFunction = trick
 
    // prints "No treats!" 
    trick()
    // prints "No treats!" again
    trickFunction()
 
}
 
val trick = {
    println("No treats!")
}

4. Use functions as a data type

Use a function as a return type

val treat: () -> Unit = {
    println("Have a treat!")
}
val trick = {
    println("No treats!")
}
 
val treat = {
    println("Have a treat!")
}
 
fun trickOrTreat(isTrick: Boolean): () -> Unit {
    if (isTrick) {
        return trick
    } else {
        return treat
    }
}

Pass a function to another function as an argument

// the second parameter is a function, which has an Int parameter and returns String 
fun trickOrTreat(isTrick: Boolean, extraTreat: (Int) -> String): () -> Unit {
    if (isTrick) {
        return trick
    } else {
        println(extraTreat(5))
        return treat
    }
}
 
fun main() {
    val coins: (Int) -> String = { quantity ->
        "$quantity quarters"
    }
 
    val cupcake: (Int) -> String = {
        "Have a cupcake!"
    }
 
    val treatFunction = trickOrTreat(false, coins)
    val trickFunction = trickOrTreat(true, cupcake)
    treatFunction()
    trickFunction()
}

Nullable function types

Like other data types, function types can be declared as nullable. In these cases, a variable could contain a function or it could be null.

To declare a function as nullable, surround the function type in parentheses followed by a ? symbol outside the ending parenthesis.

fun trickOrTreat(isTrick: Boolean, extraTreat: ((Int) -> String)?): () -> Unit {
    if (isTrick) {
        return trick
    } else {
        if (extraTreat != null) {
            println(extraTreat(5))
        }
        return treat
    }
}
 
fun main() {
    val coins: (Int) -> String = { quantity ->
        "$quantity quarters"
    }
 
    val treatFunction = trickOrTreat(false, coins)
    val trickFunction = trickOrTreat(true, null)
    treatFunction()
    trickFunction()
}

5. Write lambda expressions with shorthand syntax

Omit parameter name

it is used as parameter name:

val coins: (Int) -> String = {
    "$it quarters"
}

Pass a lambda expression directly into a function

fun main() {
    val treatFunction = trickOrTreat(false, { "$it quarters" })
    val trickFunction = trickOrTreat(true, null)
    treatFunction()
    trickFunction()
}

Use trailing lambda syntax

You can use another shorthand option to write lambdas when a function type is the last parameter of a function.

val treatFunction = trickOrTreat(false) { "$it quarters" }

6. Use the repeat() function

fun main() {
    val treatFunction = trickOrTreat(false) { "$it quarters" }
    val trickFunction = trickOrTreat(true, null)
    repeat(4) {
        treatFunction()
    }
    trickFunction()
}

7.Conclusion

Summary

6 Practice: Kotlin Fundamentals

…

7 What's next?

…