Connect to platform-specific APIs
If you're developing a multiplatform application that needs to access platform-specific APIs that implement the required functionality (for example, generating a UUID), 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.

The compiler ensures that every declaration marked with the expect
keyword in the common module has the corresponding declarations marked with the actual
keyword in all platform modules. The IDE provides tools that help you create the missing actual declarations.
Learn how to add dependencies on platform-specific libraries.
Examples
For simplicity, the following examples use intuitive target names, like iOS and Android. However, in your Gradle build files, you need to use a specific target name from the list of supported targets.
Generate a UUID
Let's assume that you are developing iOS and Android applications using Kotlin Multiplatform and you want to generate a universally unique identifier (UUID):

For this purpose, declare the expected function randomUUID()
with the expect
keyword in the common module. Don't include any implementation code.
In each platform-specific module (iOS and Android), provide the actual implementation for the function randomUUID()
expected in the common module. Use the actual
keyword to mark the actual implementation.
The following examples show the implementation of this for Android and iOS. Platform-specific code uses the actual
keyword and the expected name for the function.
Implement a logging framework
Another example of code sharing and interaction between the common and platform logic, JS and JVM in this case, in a minimalistic logging framework:
For JavaScript, a completely different set of APIs is available, and the actual
declaration will look like this.
Send and receive messages from a WebSocket
Consider developing a chat platform for iOS and Android using Kotlin Multiplatform. Let's see how you can implement sending and receiving messages from a WebSocket.
For this purpose, define a common logic that you don't need to duplicate in all platform modules – just add it once to the common module. However, the actual implementation of the WebSocket class differs from platform to platform. That's why you should use expect
/actual
declarations for this class.
In the common module, declare the expected class PlatformSocket()
with the expect
keyword. Don't include any implementation code.
In each platform-specific module (iOS and Android), provide the actual implementation for the class PlatformSocket()
expected in the common module. Use the actual
keyword to mark the actual implementation.
The following examples show the implementation of this for Android and iOS.
Android implementation uses the third-party library OkHttp. Add the corresponding dependency to build.gradle(.kts)
in the shared module:
iOS implementation uses NSURLSession
from the standard Apple SDK and doesn't require additional dependencies.
And here is the common logic in the common module that uses the platform-specific class PlatformSocket()
.
Rules for expected and actual declarations
The main rules regarding expected and actual declarations are:
An expected declaration is marked with the
expect
keyword; the actual declaration is marked with theactual
keyword.expect
andactual
declarations have the same name and are located in the same package (have the same fully qualified name).expect
declarations never contain any implementation code and are abstract by default.In interfaces, functions in
expect
declarations cannot have bodies, but theiractual
counterparts can be non-abstract and have a body. It allows the inheritors not to implement a particular function.To indicate that common inheritors don't need to implement a function, mark it as
open
. All itsactual
implementations will be required to have a body:// Common expect interface Mascot { open fun display(): String } class MascotImpl : Mascot { // it's ok not to implement `display()`: all `actual`s are guaranteed to have a default implementation } // Platform-specific actual interface Mascot { actual fun display(): String { TODO() } }
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: