Connect to platform-specific APIs

    If you’re developing a multiplatform application that needs to access platform-specific APIs that implement the required functionality, use the Kotlin mechanism of expected and actual declarations.

    With this mechanism, a common source set defines an expected declaration, and platform source sets must provide the actual declaration that corresponds to the expected declaration. This works for most Kotlin declarations, such as functions, classes, interfaces, enumerations, properties, and annotations.

    1. //Android
    2. import java.util.*
    3. actual fun randomUUID() = UUID.randomUUID().toString()

    Here’s another example of code sharing and interaction between the common and platform logic in a minimalistic logging framework.

    1. //Common
    2. enum class LogLevel {
    3. DEBUG, WARN, ERROR
    4. }
    5. internal expect fun writeLogMessage(message: String, logLevel: LogLevel)
    6. fun logDebug(message: String) = writeLogMessage(message, LogLevel.DEBUG)
    7. fun logWarn(message: String) = writeLogMessage(message, LogLevel.WARN)
    8. fun logError(message: String) = writeLogMessage(message, LogLevel.ERROR)

    expected platform-specific API

    expected API can be used in the common code

    It expects the targets to provide platform-specific implementations for writeLogMessage, and the common code can now use this declaration without any consideration of how it is implemented.

    For JavaScript, a completely different set of APIs is available, and the actual declaration will look like this.

    1. //JS
    2. internal actual fun writeLogMessage(message: String, logLevel: LogLevel) {
    3. LogLevel.DEBUG -> console.log(message)
    4. LogLevel.WARN -> console.warn(message)
    5. }
    6. }
    • An expected declaration is marked with the expect keyword; the actual declaration is marked with the actual keyword.
    • expect and actual declarations have the same name and are located in the same package (have the same fully qualified name).

    During each platform compilation, the compiler ensures that every declaration marked with the expect keyword in the common or intermediate source set has the corresponding declarations marked with the actual keyword in all platform source sets. The IDE provides tools that help you create the missing actual declarations.

    If you have a platform-specific library that you want to use in shared code while providing your own implementation for another platform, you can provide a typealias to an existing class as the actual declaration:

    We recommend that you use expected and actual declarations only for Kotlin declarations that have platform-specific dependencies. It is better to implement as much functionality as possible in the shared module even if doing so takes more time.

    Don’t overuse expected and actual declarations – in some cases, an interface may be a better choice because it is more flexible and easier to test.