Kotlin Multiplatform: Expect/Actuals in Less Than Five Minutes
Tags: kotlin, ios, android
Published: 2019-09-11 18:31:20

If you're reading this you've probably heard a lot about Kotlin Multiplatform, but aren't sure where to start. The platform is evolving fast, which means a lot of the docs are out of date, and/or can be a little overwhelming. But nobody likes reading the directions, so I'm writing a series of posts that take about 5 minutes each to run through, and introduce the basics on Kotlin Multiplatform.

Part 1 gets you starting from nothing. This is part 2, which focuses on `expect`/`actual` statements. Kotlin's native interop is one of its most distinguishing features. Unlike other "cross platform" ecosystems, Kotlin is designed to embrace the native platform it is integrating with. `expect`/`actual` statements are one of the main mechanisms it provides to do that.


---

_Five minutes? Well, yes, if you've already gone through the [previous Kotlin Multiplatform article](https://medium.com/@ben_98270/two-apps-in-less-than-five-minutes-with-kotlin-multiplatform-bedf454a4a7b) and completed it. We're starting [where Part 1 left off](https://github.com/touchlab/KotlinMultiplatformStarter/tree/starter/expect/actuals)._

---

One area that requires platform-specific logic is dealing with dates. We're going to create a simple `expect` class, `KMPDate`, which takes a date format string and lets you create a formatted string representing today's date. 

First, open `/app/src/commonMain/kotlin/sample/Sample.kt`. Underneath the `Greeting` class, create a new `expect` class:

```kotlin
expect class KMPDate(formatString: String) {
    fun asString(): String
}
```

The `expect` keyword declares that the common code can expect different `actual` implementations for each platform. In this case, `expect` applies to a class. However, it can also apply to functions, objects, annotations, etc. See [here](https://kotlinlang.org/docs/reference/platform-specific-declarations.html) for more.

Go to `/app/src/main/java/sample/SampleAndroid.kt` to create the `actual` Android implementation. Underneath the `MainActivity` class, add the following:

```kotlin
actual class KMPDate actual constructor(formatString: String) { // 1

    private val dateFormat = SimpleDateFormat(formatString) // 2

    actual fun asString(): String {
        return dateFormat.format(Date()) // 3
    }
}
```

1. The expect declaration of `KMPDate` stated that it takes a `formatString`, so an `actual constructor` implementation accompanies the `actual class` implementation.

2. Create a `SimpleDateFormat` object using the `formatString`. iOS has an `NSDateFormatter` class, which is similar to `SimpleDateFormat`, but we'll get to later. There is currently no common Kotlin implementation, but for most things, Android and iOS have equivalent features available.

3. The `SimpleDateFormat` object formats `Date()` - which produces a `Date` object representing today's date - into a string.

Next, go to `app/src/iosMain/kotlin/sample/SampleIos.kt`, which is currently empty. Paste in the following:

```kotlin
actual class KMPDate actual constructor(formatString: String) { // 1

    private val dateFormatter = NSDateFormatter().apply { // 2
        this.dateFormat = formatString
    }

    actual fun asString(): String {
        return formatter.stringFromDate(NSDate()) // 3 
    }
}
```

1. Identical to the `actual class` declaration on the Android side.

2. Pass `formatString` into an iOS `NSDateFormatter` object, which - as mentioned earlier - achieves the same result as `SimpleDateFormat` on Android.

3. The `NSDateFormatter` object formats a string based on `NSDate()` - which produces an `NSDate` object representing today.

Finally, go back to `/app/src/commonMain/kotlin/sample/Sample.kt`. Inside of the `Greeting` class, create a `KMPDate` object that takes "MMM dd" as its date format:

```kotlin
private val date = KMPDate("MMM dd")
```

And last but not least, use string interpolation to insert the formatted date string from each platform into the value of `hello()`:

```kotlin
fun hello(): String =  "Hello, Android and iOS worlds, today is ${date.asString()}!"
```

All done! Run you Android and iOS apps and see the dates displayed on each platform!

If you come from an iOS background and want a deeper explanation of how to use Kotlin Multiplatform to make a more involved app, then you might want to check out [this article](https://www.infoq.com/articles/kotlin-multiplatform-ios-developers/) I wrote.

As you can see, it's all about starting small with Kotlin Multiplatform. We recently launched The Touchlab Refactory; an incremental refactoring service with KMP which focuses on a single feature at a time with no disruption to your current development workflow. Learn more [here](https://touchlab.co/refactory/). 

[We're hiring!](https://touchlab.co/about-us/#careers)