My conspectus of:
https://developer.android.com/courses/pathways/android-basics-compose-unit-2-pathway-1
… Optional video …
if / else statementsfun 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") } }
when statementswhen statements are preferred when there are more than two branches to consider.fun main() { val trafficLightColor = "Black" when (trafficLightColor) { "Red" -> println("Stop") "Yellow" -> println("Slow") "Green" -> println("Go") else -> println("Invalid traffic-light color") } }
when without parameterwhen { 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.") }
in keyword for a range of conditionswhen (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.") }
is keyword to check data typewhen (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.") }
if/else and when as expressionsfun 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) }
String type is non-nullable (!)? operator to the end of the type. String? type can hold either a string or null, whereas a String type can only hold a string.?. safe call operatorfun main() { var favoriteActor: String? = null println(favoriteActor?.length) // => prints "null" }
!! not-null assertion operator?. safe-call operators, the use of a !! not-null assertion operator may result in a NullPointerException error being thrown if the nullable variable is indeed null. Thus, it should be done only when the variable is always non-nullable or proper exception handling is set in place. When not handled, exceptions cause runtime errors.if/else expressionsfun 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.") }
?: Elvis operator?: Elvis operator executes. If the variable is null, the expression after the ?: Elvis operator executes.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.") }
class SmartDevice { // empty body }
fun main() { val smartTvDevice = SmartDevice() }
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() }
val keyword and a mutable property with the var keyword.var speakerVolume = 2 get() = field set(value) { field = value }
set() function, if you try to assign the value parameter to the speakerVolume property itself, the code enters an endless loop because the Kotlin runtime tries to update the value for the speakerVolume property, which triggers a call to the setter function repeatedly.class SmartDevice constructor() {
...
}
class SmartDevice {
...
}
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"
}
}
...
}
open to make a class extendableopen class SmartDevice(val name: String, val category: String) { ... }
class SmartTvDevice(deviceName: String, deviceCategory: String) : SmartDevice(name = deviceName, category = deviceCategory) { }
val / var keywords for parameters). This means that the deviceName and deviceCategory parameters are merely constructor parameters instead of class properties. You won't be able to use them in the class, but simply pass them to the superclass constructor.override keywordclass 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" ... }
open class SmartDevice protected constructor (val name: String, val category: String) {
// ...
}
internal open class SmartDevice(val name: String, val category: String) {
// ...
}
var type, you need to implement the ReadWriteProperty interface. Similarly, you need to implement the ReadOnlyProperty interface for the val type.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)
...
}
…
…
…
…
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!") }
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 } }
// 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() }
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() }
it is used as parameter name:
val coins: (Int) -> String = { "$it quarters" }
fun main() { val treatFunction = trickOrTreat(false, { "$it quarters" }) val trickFunction = trickOrTreat(true, null) treatFunction() trickFunction() }
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" }
fun main() { val treatFunction = trickOrTreat(false) { "$it quarters" } val trickFunction = trickOrTreat(true, null) repeat(4) { treatFunction() } trickFunction() }
…
…