· 3 min read Posted by Ben Whitley
Kotlin Multiplatform in Five Minutes or Less: Expect / Actuals Statements
If you’re reading this you’ve probably heard a lot about Kotlin Multiplatform, but aren’t sure where to start, you can always check out our intro to Kotlin Multiplatform guide too. 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 and completed it. We’re starting where Part 1 left off.
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:
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 for more.
Go to /app/src/main/java/sample/SampleAndroid.kt to create the actualAndroid implementation. Underneath the MainActivity class, add the following:
actual class KMPDate actual constructor(formatString: String) { // 1
private val dateFormat = SimpleDateFormat(formatString) // 2
actual fun asString(): String {
return dateFormat.format(Date()) // 3
}
}
- The
expectdeclaration ofKMPDatestated that it takes aformatString, so anactual constructorimplementation accompanies theactual classimplementation. - Create a
SimpleDateFormatobject using theformatString. iOS has anNSDateFormatterclass, which is similar toSimpleDateFormat, but we’ll get to later. There is currently no common Kotlin implementation, but for most things, Android and iOS have equivalent features available. - The
SimpleDateFormatobject formatsDate()— which produces aDateobject 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:
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
}
}
- Identical to the
actual classdeclaration on the Android side. - Pass
formatStringinto an iOSNSDateFormatterobject, which — as mentioned earlier — achieves the same result asSimpleDateFormaton Android. - The
NSDateFormatterobject formats a string based onNSDate()— which produces anNSDateobject 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:
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():
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 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.