kotlin
✓Verified·Scanned 2/18/2026
Build robust Android and multiplatform apps with Kotlin idioms, coroutines, and null safety.
from clawhub.ai·vc5f0a55·3.8 KB·0 installs
Scanned from 1.0.0 at c5f0a55 · Transparency log ↗
$ vett add clawhub.ai/ivangdavila/kotlin
Kotlin Development Rules
Null Safety
?.safe call chains —user?.address?.cityreturns null if any is null?:Elvis for defaults —name ?: "Unknown"is cleaner than if-else!!asserts non-null — crashes on null, use only when you've already checkedletfor null-scoped operations —user?.let { doSomething(it) }only runs if non-null- Platform types from Java are risky — add null checks or use
@Nullable/@NonNullannotations
Coroutines
suspendfunctions only callable from coroutines — don't block, usewithContext(Dispatchers.IO)for IOlaunchfor fire-and-forget —async/awaitwhen you need the resultviewModelScopeauto-cancels on ViewModel clear — don't useGlobalScopein Androidflowfor reactive streams — collect in lifecycle-aware scope withrepeatOnLifecycle- Structured concurrency: child coroutine failure cancels parent — use
supervisorScopeto isolate failures
Collections
listOfis immutable — usemutableListOfif you need to modifymap,filter,reduceare lazy on Sequences — use.asSequence()for large chainsfirst()throws on empty — usefirstOrNull()for safe accessassociateandgroupByreplace manual map building — cleaner than forEach with mutableMap- Destructuring:
for ((key, value) in map)— also works with data classes
Data Classes
data classauto-generatesequals,hashCode,copy,toString— don't write manually- Only constructor properties in
equals/hashCode— body properties ignored copy()for immutable updates —user.copy(name = "New")keeps other fields- Prefer data classes for DTOs and state — but not for entities with identity beyond data
Scope Functions
letfor null checks and transformations —value?.let { use(it) }applyfor object configuration —MyObject().apply { prop = value }returns objectrunfor scoped computation —val result = obj.run { compute() }returns resultalsofor side effects —value.also { log(it) }returns original- Don't nest scope functions — readability drops fast, extract to named functions
Extension Functions
- Extend existing classes without inheritance —
fun String.isEmail(): Boolean - Keep extensions close to usage — don't scatter across codebase
- Extension on nullable:
fun String?.orEmpty()— can be called on null - Extensions are resolved statically — not polymorphic, receiver type matters at compile time
Sealed Classes
- Exhaustive
when— compiler ensures all subclasses handled - Perfect for state machines and results —
sealed class Result<T> { Success, Error } - Subclasses must be in same file (or same package in Kotlin 1.5+) — intentional restriction
sealed interfacefor multiple inheritance — when you need to implement other interfaces
Common Mistakes
==is structural equality in Kotlin —===for reference, opposite of Java- String templates:
"$var"or"${expr}"— no concatenation needed lateinitcan't be primitive — useby lazyfor computed initializationobjectis singleton —companion objectfor static-like members, not instance- SAM conversion only for Java interfaces — Kotlin interfaces need explicit
fun interface
Interop with Java
@JvmStaticfor companion methods callable as static — without it, needCompanion.method()@JvmOverloadsgenerates overloads for default params — Java doesn't see defaults otherwise@JvmFieldexposes property as field — without getter/setter for Java callers- Nullability annotations propagate — annotate Java code for Kotlin safety