Irbisa · Cheatsheet
Kotlin OOP & Functional
Classes, data classes, sealed classes, objects, extension functions, scope functions
What is a
data class, what does the compiler generate for it, and what are its limits?data class User(val id: Long, val name: String) { var lastSeen: Long = 0 // body property: not part of equals/toString} val a = User(1, "Alice")val b = a.copy(name = "Alicia") // new instance, id kept…What are sealed classes and sealed interfaces, and how do they make
whenexhaustive?sealed interface LoginState { data object Idle : LoginState data object Loading : LoginState data class Success(val userId: Long) : LoginState data class Error(val message: String) : LoginState}…What is an
enum class, can its constants hold data, and when is a sealed class the better choice?enum class OrderStatus(val label: String) { PENDING("Waiting"), SHIPPED("On the way"), UNKNOWN("Unknown"); companion object {…What is the difference between an abstract class and an interface in Kotlin, and why are classes final by default?
interface Logger { val tag: String // no backing field allowed fun log(msg: String) = println("[$tag] $msg") // default body} abstract class BaseRepo(protected val baseUrl: String) { // state + constructor…What are the four OOP principles, and what is the difference between overloading and overriding?
Which visibility modifiers does Kotlin have, and what does
internalactually cover?What are extension functions and properties, how are they compiled, and can they access private members?
// StringExt.ktfun String.initials(): String = split(" ").filter { it.isNotBlank() }.joinToString("") { it.first().uppercase() } val String.isEmail: Boolean // no backing field, computed on each read get() = contains('@')…What is an
infixfunction, and what rules must it follow?infix fun Int.percentOf(total: Int): Int = this * total / 100 val tax = 20 percentOf 150 // 30val pair = "id" to 42 // Pair("id", 42)for (i in 0 until 10 step 2) print(i) // 02468…What is the difference between the scope functions
let,run,with,applyandalso?val length: Int? = name?.let { it.length } // null-safe transform val intent = Intent(context, DetailActivity::class.java).apply { putExtra("id", id) // this = Intent addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)}…What is the
equals/hashCodecontract, and why must you override both together?open class User(val id: Long, var displayName: String) { override fun equals(other: Any?): Boolean { if (this === other) return true if (other == null || javaClass != other.javaClass) return false return id == (other as User).id // entity: id only, displayName is mutable }…What is the difference between a nested class and an
innerclass in Kotlin, and how caninnerleak a Fragment?class Outer(private val name: String) { class Nested { fun describe() = "no access to name" // no outer reference } inner class Inner { fun describe() = "inner of ${this@Outer.name}" // holds Outer…What does this code print, and what does each of
apply,also,letandrunreturn?val list = mutableListOf(1, 2) val a = list.apply { add(3) }val b = list.also { it.add(4) }.sizeval c = list.let { it.add(5) }val d = list.run { size } println(a)println("$b $c $d")What is the difference between
class,objectandcompanion object, and is anobjectsingleton thread-safe?object Analytics { // one instance, created on first access private val events = mutableListOf<String>() @Synchronized fun track(e: String) { events += e } // state still needs guarding} class User private constructor(val name: String) {…In what order do the companion object, property initializers,
initblocks and a secondary constructor run?class User(val name: String, age: Int) { companion object { init { println("0 companion") } } // once per class load val greeting = "Hello, $name".also { println("1 initializer") } init {…What does this code print, and what does it tell you about
copy()on adata class?data class Cart(val owner: String, val items: MutableList<String>) val original = Cart("ann", mutableListOf("tea"))val copy = original.copy(owner = "bob")copy.items += "milk" println(original.items)println(original == copy)println(original.items === copy.items)What does this code print, and how are extension functions dispatched compared to member functions?
open class Shape { open fun name() = "Shape" }class Circle : Shape() { override fun name() = "Circle" } fun Shape.label() = "shape"fun Circle.label() = "circle"fun Circle.name() = "extension" fun main() { val s: Shape = Circle() println(s.name()) println(s.label()) println(Circle().name())}Find the bug: finished downloads never leave
active, andactiveCount()only grows.data class Download(val url: String, var progress: Int = 0) class DownloadTracker { private val active = HashSet<Download>() fun start(url: String): Download = Download(url).also { active += it } fun onProgress(d: Download, percent: Int) { d.progress = percent } fun finish(d: Download) { active.remove(d) } fun activeCount() = active.size}Why does
for (d in downloads) if (d.done) downloads.remove(d)throwConcurrentModificationExceptionon one thread, and how do you fix it?data class Download(val id: Long, val done: Boolean) val downloads = mutableListOf( Download(1, done = true), Download(2, done = false), Download(3, done = true))…What is a callable reference (
::), and what does a bound reference likeviewModel::onSubmitcapture?class SubmitViewModel { fun onSubmit(text: String) { /* ... */ }} val vm = SubmitViewModel()val bound: (String) -> Unit = vm::onSubmit // receiver fixed here…How does operator overloading work in Kotlin, and how do you make
+,[]andinwork on your own type?@JvmInlinevalue class Money(val cents: Long) : Comparable<Money> { operator fun plus(other: Money) = Money(cents + other.cents) operator fun times(factor: Int) = Money(cents * factor) override fun compareTo(other: Money) = cents.compareTo(other.cents)}…What is the difference between a
Sequencepipeline and aListpipeline, and when doesasSequence()hurt?val firstThree = generateSequence(1) { it + 1 } // infinite source .filter { println("filter $it"); it % 2 == 0 } .map { println("map $it"); it * it } .take(3) .toList() // terminal: starts the work// prints filter 1, filter 2, map 2, filter 3, filter 4, map 4, ... one element at a time…What is SAM conversion, and what does
fun interfaceadd for Kotlin interfaces?fun interface Validator { fun validate(s: String): Boolean} val notBlank = Validator { it.isNotBlank() } // SAM constructorfun check(v: Validator, input: String) = v.validate(input)…Why is composition often preferred over inheritance, and how does Kotlin's
byinterface delegation support it?class User(val id: Long) interface Repo { fun load(id: Long): User fun refresh()}…What are the SOLID principles? Give an Android example of each and one violation.
Is Singleton an anti-pattern on Android, and how do you keep one instance without a global
object?