kotlinadvanced
Kotlin Multiplatform — Expect/Actual Declarations
Share code across platforms with expect/actual: common interfaces, platform-specific implementations.
kotlinPress ⌘/Ctrl + Shift + C to copy
// ============================================
// commonMain/src/Platform.kt
// ============================================
// Expect declarations — common interface
expect fun platformName(): String
expect fun currentTimeMillis(): Long
expect class UUID {
companion object {
fun randomUUID(): UUID
}
override fun toString(): String
}
// Common code using expect declarations
class AppInfo {
val platform = platformName()
val startTime = currentTimeMillis()
val instanceId = UUID.randomUUID().toString()
fun info() = "App on $platform (id: $instanceId)"
}
// Common business logic
interface Repository<T> {
suspend fun findAll(): List<T>
suspend fun findById(id: String): T?
suspend fun save(item: T)
suspend fun delete(id: String)
}
data class Note(
val id: String = UUID.randomUUID().toString(),
val title: String,
val content: String,
val timestamp: Long = currentTimeMillis()
)
expect class NotesRepository() : Repository<Note>
// Shared ViewModel
class NotesViewModel(private val repo: NotesRepository = NotesRepository()) {
suspend fun getAllNotes(): List<Note> = repo.findAll()
suspend fun addNote(title: String, content: String) {
repo.save(Note(title = title, content = content))
}
suspend fun removeNote(id: String) = repo.delete(id)
}
// ============================================
// jvmMain/src/PlatformJvm.kt
// ============================================
/*
actual fun platformName(): String = "JVM ${System.getProperty("java.version")}"
actual fun currentTimeMillis(): Long = System.currentTimeMillis()
actual class UUID private constructor(private val impl: java.util.UUID) {
actual companion object {
actual fun randomUUID(): UUID = UUID(java.util.UUID.randomUUID())
}
actual override fun toString() = impl.toString()
}
actual class NotesRepository actual constructor() : Repository<Note> {
private val notes = mutableListOf<Note>()
override suspend fun findAll() = notes.toList()
override suspend fun findById(id: String) = notes.find { it.id == id }
override suspend fun save(item: Note) { notes.add(item) }
override suspend fun delete(id: String) { notes.removeIf { it.id == id } }
}
*/
// ============================================
// jsMain/src/PlatformJs.kt
// ============================================
/*
import kotlin.js.Date
actual fun platformName(): String = "JS/Browser"
actual fun currentTimeMillis(): Long = Date.now().toLong()
actual class UUID private constructor(private val value: String) {
actual companion object {
actual fun randomUUID(): UUID {
val chars = "0123456789abcdef"
val uuid = buildString {
repeat(32) { append(chars.random()) }
}
return UUID(uuid)
}
}
actual override fun toString() = value
}
actual class NotesRepository actual constructor() : Repository<Note> {
private val notes = mutableListOf<Note>()
override suspend fun findAll() = notes.toList()
override suspend fun findById(id: String) = notes.find { it.id == id }
override suspend fun save(item: Note) { notes.add(item) }
override suspend fun delete(id: String) { notes.removeIf { it.id == id } }
}
*/Use Cases
- Sharing business logic across JVM and JS
- Platform-specific API abstraction
- Multiplatform library development
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
kotlinbeginner
Null Safety — Elvis, Safe Call, and let
Master Kotlin null safety: safe calls, Elvis operator, let/also scoping, and smart casts.
Best for: Safe navigation through nullable chains
#kotlin#null-safety
kotlinbeginner
Data Classes — Copy, Destructure, and Equals
Use data classes for immutable models: auto-generated equals, hashCode, copy, and destructuring.
Best for: Immutable domain models and DTOs
#kotlin#data-class
kotlinbeginner
Extension Functions and Properties
Add methods to existing classes without inheritance: extension functions, properties, and generic extensions.
Best for: Adding utility methods to third-party types
#kotlin#extensions
kotlinbeginner
Scope Functions — let, run, apply, also, with
Master Kotlin scope functions: when to use let, run, apply, also, and with for concise code.
Best for: Object initialization and configuration
#kotlin#scope-functions