Skip to content

Kotlin Multiplatform Common — Complete Guide

DodaTech Updated 2026-06-24 2 min read

In this tutorial, you'll learn about Kotlin Multiplatform Common. We cover key concepts, practical examples, and best practices.

The Problem

Your KMP project doesn't compile because expect functions don't have matching actual implementations, or common code can't use platform-specific APIs.

Wrong Approach ❌

// expect declaration without actual on all platforms
expect fun getPlatformName(): String
// Missing actual in androidMain and iosMain!
// Putting platform code in commonMain
// commonMain
fun formatDate(date: Date): String { // Date is JVM-only!
    return SimpleDateFormat("yyyy-MM-dd").format(date)
}

Output: Compilation error: Actual declaration for expect fun getPlatformName() not found. Platform type in common code.

Right Approach ✅

// commonMain
// Define your expect declarations
expect fun getPlatformName(): String

// Common business logic — no platform types
data class User(val id: String, val name: String)

// Use interfaces for platform-specific behavior
expect class PlatformContext

expect class Database {
    fun saveUser(user: User)
    fun getUser(id: String): User?
}

// Common code using expects
class UserRepository(private val db: Database) {
    fun greet(): String = "Hello from ${getPlatformName()}"
    fun save(user: User) = db.saveUser(user)
}

// androidMain
actual fun getPlatformName(): String = "Android ${Build.VERSION.SDK_INT}"

actual class Database(private val context: PlatformContext) {
    actual fun saveUser(user: User) { /* Room DB */ }
    actual fun getUser(id: String): User? { /* Room query */ }
}

// iosMain
actual fun getPlatformName(): String = "iOS ${UIDevice.currentDevice.systemVersion}"

actual class Database {
    actual fun saveUser(user: User) { /* CoreData */ }
    actual fun getUser(id: String): User? { /* CoreData fetch */ }
}

// Use kotlinx-datetime for cross-platform date handling
// In build.gradle.kts:
// commonMain.dependencies { implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.6.0") }

Output: KMP project compiles across all platforms with proper expect/actual.

Prevention

  • Keep business logic in commonMain.
  • Use expect/actual for platform-specific APIs.
  • Never put platform-specific types in commonMain.
  • Use KMP-compatible libraries (kotlinx-datetime, kotlinx-serialization).
  • Use @OptionalExpectation for optional actual declarations.

Common Mistakes with multiplatform common

  1. Forgetting that lazy evaluation defers computation until the value is forced, causing space leaks with unevaluated thunks
  2. Using return to exit a function early instead of wrapping a pure value in the monad
  3. Mixing let bindings with <- bindings in do notation, producing type errors

These mistakes appear frequently in real-world KOTLIN code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

### What is the difference between expect/actual and interfaces?

expect/actual is a compile-time mechanism — each platform must provide its actual. Interfaces with dependency injection are runtime alternatives. Use expect/actual for platform fundamentals (file I/O, dates, etc.).

### Can I have default implementations for expect declarations?

Use @OptionalExpectation for optional actuals, or use interfaces with default implementations. But expect functions must have an actual on every platform.

### How do I handle different API levels across platforms?

Use expect/actual for completely different implementations. For minor differences, use @Suppress("ACTUAL_WITHOUT_EXPECT") or if (platform) checks guarded by expect functions.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro