Kotlin Academy · Lektion

expect/actual-Mechanismus für Plattform-APIs

Deklarieren Sie erwartete Deklarationen im gemeinsamen Code und stellen Sie pro Plattform tatsächliche Implementierungen bereit.

Lektion 2 von 413 Schritte

expect/actual-Mechanismus für Plattform-APIs ist eine kostenlose Kotlin Academy-Lektion auf CoddyKit. Dies ist Lektion 2 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Kotlin Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Kotlin Academy-Kurs umfasst insgesamt 4 Lektionen.

Das expect/actual-Muster

expect deklariert einen API-Vertrag in commonMain. Jede Plattform stellt eine actual-Implementierung bereit. Der Compiler erzwingt, dass alle Targets eine actual-Implementierung besitzen.

// commonMain:
expect fun platformName(): String

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

// iosMain:
actual fun platformName(): String = UIDevice.currentDevice.systemName()

expect class

expect class deklariert eine Klasse mit ihrer API in commonMain. Jede Plattform stellt die vollständige Implementierung bereit.

// commonMain:
expect class DateTime {
    fun format(pattern: String): String
    val timestamp: Long
}

// androidMain:
actual class DateTime {
    actual val timestamp = System.currentTimeMillis()
    actual fun format(pattern: String): String =
        java.text.SimpleDateFormat(pattern).format(java.util.Date(timestamp))
}

expect object

expect object deklariert ein Singleton mit seinem Vertrag. Das ist nützlich für plattformspezifische Hilfsfunktionen wie Logging, Einstellungen oder Analytics.

// commonMain:
expect object Logger {
    fun debug(msg: String)
    fun error(msg: String, cause: Throwable? = null)
}

// androidMain:
actual object Logger {
    actual fun debug(msg: String) = android.util.Log.d("App", msg)
    actual fun error(msg: String, cause: Throwable?) =
        android.util.Log.e("App", msg, cause)
}

expect val / fun auf oberster Ebene

Top-Level-expect val und expect fun sind unkompliziert und eignen sich gut für zustandslose plattformspezifische Hilfsfunktionen.

// commonMain:
expect val isDebugBuild: Boolean
expect fun generateUUID(): String

// androidMain:
actual val isDebugBuild: Boolean = BuildConfig.DEBUG
actual fun generateUUID(): String = java.util.UUID.randomUUID().toString()

// iosMain:
actual val isDebugBuild: Boolean = false // or a native flag
actual fun generateUUID(): String = NSUUID().UUIDString()

expect fun mit Standardimplementierung

Seit Kotlin 1.9+ kann expect fun über expect fun f() { } eine Standardimplementierung besitzen. Plattformen können diese überschreiben oder die Standardimplementierung verwenden.

// commonMain (Kotlin 1.9+):
expect fun log(msg: String) {
    println("[DEFAULT] $msg") // used if no actual overrides
}

// androidMain:
actual fun log(msg: String) = android.util.Log.d("KMP", msg)

// iosMain (uses default):
// no actual needed — default is used

Actual Typealias

Wenn die Plattform bereits genau die benötigte Klasse besitzt, verwenden Sie actual typealias, um auf sie zu verweisen, statt sie zu wrappen.

// commonMain:
expect class AtomicInt {
    fun get(): Int
    fun incrementAndGet(): Int
}

// androidMain / jvmMain:
actual typealias AtomicInt = java.util.concurrent.atomic.AtomicInteger

// iosMain:
actual class AtomicInt {
    private var value = 0
    actual fun get() = value
    actual fun incrementAndGet() = ++value
}

expect interface (indirektes Muster)

Für mehr Flexibilität deklarieren Sie ein Interface in commonMain und verwenden expect/actual nur für die Factory, die die plattformspezifische Instanz erstellt.

// commonMain:
interface FileStorage {
    suspend fun readFile(path: String): ByteArray
    suspend fun writeFile(path: String, data: ByteArray)
}
expect fun createFileStorage(): FileStorage

// androidMain:
actual fun createFileStorage(): FileStorage = AndroidFileStorage()

// iosMain:
actual fun createFileStorage(): FileStorage = IosFileStorage()

Testen mit expect/actual

Testen Sie in commonTest die gemeinsame API. Die actual-Implementierungen werden während der plattformspezifischen Test-Tasks ausgeführt (testDebugUnitTest auf Android, iosX64Test auf iOS).

// commonTest:
import kotlin.test.Test
import kotlin.test.assertNotNull
class PlatformTest {
    @Test
    fun testUUID() {
        val uuid = generateUUID()
        assertNotNull(uuid)
        println("UUID: $uuid")
    }
}

Häufige Fehler

Jedes deklarierte expect muss in ALLEN konfigurierten Targets ein actual besitzen, andernfalls schlägt der Build fehl. Fehlende actual-Implementierungen werden zur Compile-Zeit erkannt.

// If you add a new target (e.g., jvmMain), you must add:
// actual fun platformName(): String = "JVM"
// Otherwise:
// error: Expected function platformName has no actual declaration in module :shared for JVM
fun main() { println("Missing actuals = compile error") }

Expect-Annotationsklasse

expect annotation class ermöglicht die Zuordnung plattformspezifischer Annotationen – zum Beispiel die Zuordnung einer gemeinsamen, @Parcelize ähnlichen Annotation zum Android-Parcelize-Plugin.

// commonMain:
expect annotation class CommonParcelize()

// androidMain:
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.BINARY)
actual annotation class CommonParcelize

// iosMain:
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.BINARY)
actual annotation class CommonParcelize

Praxisbeispiel: Keychain/Preferences

Ein typisches expect/actual-Praxisbeispiel ist ein Interface für sichere Speicherung, bei dem Android EncryptedSharedPreferences und iOS den Keychain verwendet.

// commonMain:
expect class SecureStorage {
    fun save(key: String, value: String)
    fun get(key: String): String?
}

// androidMain:
actual class SecureStorage {
    private val prefs = /* EncryptedSharedPreferences */ mapOf<String,String>()
    actual fun save(key: String, value: String) { /* ... */ }
    actual fun get(key: String): String? = null // simplified
}

Kurzer Check

Was geschieht zur Compile-Zeit, wenn eine expect-Deklaration für ein Target kein actual besitzt?

Zusammenfassung

expect deklariert die API in commonMain. actual stellt die plattformspezifische Implementierung bereit. Verwenden Sie actual typealias, wenn der benötigte Typ auf der Plattform bereits vorhanden ist. Fehlende actual-Implementierungen werden zur Compile-Zeit erkannt – es gibt keine Überraschungen zur Laufzeit.

Kostenlos starten

Lerne Kotlin mit einem KI-Tutor — kostenlos

Schreibe und führe echten Code in deinem Browser aus, bekomme sofortige Hilfe von einem 24/7 KI-Tutor und setze dein Lernen im Web oder in der App fort.

Kurse
51
Lektionen
203

Häufig gestellte Fragen

Ist die Lektion „expect/actual-Mechanismus für Plattform-APIs“ kostenlos?

Ja — der vollständige Text von „expect/actual-Mechanismus für Plattform-APIs“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Kotlin Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Kotlin Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „expect/actual-Mechanismus für Plattform-APIs“?

Deklarieren Sie erwartete Deklarationen im gemeinsamen Code und stellen Sie pro Plattform tatsächliche Implementierungen bereit. Du übst Kotlin Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Kotlin Academy zu starten?

Keine Vorkenntnisse erforderlich. Kotlin Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 2 von 4.

Wie lange dauert die Lektion „expect/actual-Mechanismus für Plattform-APIs“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Kotlin Academy-Lektion Code schreiben und ausführen?

Ja. Jede Kotlin Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. KMP-Projektstruktur: commonMain, androidMain, iosMain
  2. expect/actual-Mechanismus für Plattform-APIs
  3. Repository- und Use-Case-Schichten gemeinsam nutzen
  4. Dependency Injection in KMP mit Koin
← Zurück zu Kotlin Academy