Many of you have probably seen this comparison of Swift and Kotlin. It looks quite interesting, right? Yes, I agree that there are many parallels in these languages, but in this article I will focus on some aspects that make them different.

I have been an Android Developer since 2013 and most of the time I spent on developing apps in Java. Some time ago I had the opportunity to try iOS and Swift as well. I was really impressed by the fact that Swift enables writing very user-friendly code. If you put enough effort into it, your code could be like a poem.

After seven months or so I returned to Android. But instead of Java I started using Kotlin. Google announced at Google IO 2017 that Kotlin is a first-class language for Android. Therefore, I decided to learn it. It didn’t take me long to notice some significant similarities between Kotlin and Swift. But I would never say that they are the same. The following paragraphs show some of the differences between them. However, I’m not going to describe all the dissimilarities, but only those I find interesting. Let’s go through some examples.

Struct vs. Data Class a.k.a. Value and Reference types

Struct and Data Class are simplified versions of a class. We can use them in a similar way and they look alike

Kotlin:

data class Foo(var data: Int)

Swift:

struct Foo {

var data: Int

}

But as its name indicates, data class is still a class. It’s a reference type. On the other hand, struct is a value type. “So what?” you may ask. Let me explain this on an example.

Let’s create our data class in Kotlin and struct in Swift and then compare the results.

Kotlin:

var foo1 = Foo(2)

var foo2 = foo1

foo1.data = 4

Swift:

var foo1 = Foo(data: 2)

var foo2 = foo1

foo1.data = 4

What value is data for foo2 in both cases? The answer is 4 for Kotlin’s data class and 2 for Swift’s struct.

The results are different because copying a struct (var foo2 = foo1) creates an independent instance with its own unique copy of its data (like here), while copying a reference creates shared instances (like here).

If you work with Java, you are probably familiar with the Defensive Copy pattern. If not, it’s time to catch up. Here you can find more information on this topic.

In brief, there is a possibility of changing the object state by itself or its caller. The first option sounds natural and it’s a very common approach, however, the latter isn’t. Especially when you expose a reference type and you are not aware of the object’s change of state. This may lead to difficulties in finding bugs. To prevent this problem, you have to make a defensive copy of the mutable object when you pass it into or out of the class. Kotlin is much more helpful in such situations than Java, but some issues can still occur if you are not careful enough. Consider this simplified example:

data class Page(val title: String) class Book { val pages: MutableList<Page> = mutableListOf(Page(“Chapter 1”), Page(“Chapter 2”))

}

I declared pages as a MutableList because I want to modify them inside this object (add, remove etc.). The pages are not private because I want to make it possible to read the current state by the caller. So far, so good.

val book = Book()

print(“$book”) // Book(pages=[Page(title=Chapter 1), Page(title=Chapter 2)])

Now I can read the current state of the book like so:

val bookPages = book.pages

I add a new Page to the bookPages list and I use it later on



bookPages.add(Page(“Chapter 3”))

Unfortunately, I have changed the book state too. That wasn’t my intention…

print(“$book”) // Book(pages=[Page(title=Chapter 1), Page(title=Chapter 2), Page(title=Chapter 3)])

We can use a defensive copy pattern to overcome this obstacle. It’s a piece of cake in Kotlin.

book.pages.toMutableList()

We are safe and sound :)

What about Swift? It’s for free! Yes, arrays are structs, structs are a value type as was mentioned before, so when you write:

var bookPages = book.pages

you are working on a copy of the pages list.

So we are dealing with a value type again. It’s very important to understand the differences if you don’t want to experience difficulties with debugging :) Many “objects” are a struct in Swift, for example, enum, Int, CGPoint, Array, etc.

Interface & Protocol & Extension

This is my favourite topic :D

Let’s start with comparing Interface and Protocol. Basically, they are the same.

Both can require specific methods to be implemented by (conforming in Swift, implementing in Kotlin) the class/struct;

Both can require a specific property to be provided. Property can be settable and gettable or only gettable;

Both* allow you to add a default implementation of method.

Besides, the protocol can require a specific initializer (a constructor according to Kotlin’s terminology).

Kotlin:

interface MyInterface {

var myVariable: Int

val myReadOnlyProperty: Int fun myMethod()

fun myMethodWithBody() {

// implementation goes here

}

}

Swift:

protocol MyProtocol {

init(parameter: Int) var myVariable: Int { get set }

var myReadOnlyProperty: Int { get }



func myMethod()

func myMethodWithBody()

} extension MyProtocol {



func myMethodWithBody() {

// implementation goes here

}

}

*You’ll notice you can’t add a default implementation of method inside the protocol directly. That’s why I added an asterisk to the last point on the list. You have to create an extension for that. And in this nice way, you can move on to the more interesting part — extensions!

Extensions enable adding some extra functionalities to the existing class (or struct ;)) without inheriting from them. It’s as simple as that. You have to agree that this is a really powerful feature.

It’s something new for Android developers, that’s why we love using it everywhere! Creating an extension in Kotlin is not rocket science.

You can create an extension for properties:

val Calendar.yearAhead: Calendar

get() {

this.add(Calendar.YEAR, 1)

return this

}

or functions:

fun Context.getDrawableCompat(@DrawableRes drawableRes: Int): Drawable {

return ContextCompat.getDrawable(this, drawableRes)

?: throw NullPointerException(“Can not find drawable with id = $drawableRes”)

}

As you can see, we haven’t used any keywords here.

Kotlin has some predefined extensions which are also cool, e.g. “orEmpty()” for an optional string:

var maybeNullString: String = null

titleView.setText(maybeNullString.orEmpty())

This valuable extension looks like this:

public inline fun String?.orEmpty(): String = this ?: ""

‘?:’ tries to unwrap ‘this’ which is the current value of our string. If it’s null, then it returns an empty string instead.

Ok, let’s have a look at Swift extensions.

The definition is the same and I don’t want to sound like a broken record.

If you’re looking for an extension similar to “orEmpty()”, you’re doomed to fail.. But it’s not a problem to create one on your own, right? Let’s try!

extension String? {

func orEmpty() -> String {

return self ?? ""

}

}

but then you will see:

An optional value in Swift is a generic enum with a specified type called Wrapped. In our case, Wrapped is a string, so the extension should look like this:

extension Optional where Wrapped == String {

func orEmpty() -> String {

switch self {

case .some(let value):

return String(describing: value)

case _:

return ""

}

}

}

and usage:

let page = Page(text: maybeNilString.orEmpty())

It’s much more complex than the Kotlin variant, isn’t it? Unfortunately, there’s another drawback. As you already know, Optional in Swift is a generic enum, so your extension will be applied for all types. Well, this doesn’t sound good:

However, the compiler protects you and it won’t compile this code. But if you add more similar extensions, you will have a mess in your hint box anyway.

So, are Kotlin’s extensions better implemented than Swift’s? I would say Swift’s extensions are designed for different purposes ;). Hold on tight Android developers!

Protocols and extensions are created to work together. You can create your own protocol and an extension for a class to adopt your protocol. This might sound crazy — and it’s not the end! There is also something called Conditionally Conforming to a Protocol. It means that a class/struct can conform to the protocol when certain conditions are met.

Let’s say there are many places in an app where a pop up alert is needed. We love the DRY principle and don’t want to copy and paste the alert creation code everywhere. We can resolve this problem using a protocol and an extension.

First, create a protocol:

protocol AlertPresentable {

func presentAlert(message: String)

}

Then, an extension with a default implementation:

extension AlertPresentable {



func presentAlert(message: String) {

let alert = UIAlertController(title: “Alert”, message: message, preferredStyle: .alert)

alert.addAction(UIAlertAction(title: “OK”, style: .default, handler: nil))

}

}

Ok, the presentAlert method only creates the alert, but doesn’t present anything. We need a view controller reference for that. Should we pass it through an argument into the method? Meh, it’s not a good idea. Let’s use the Where clause!

extension AlertPresentable where Self : UIViewController {



func presentAlert(message: String) {

let alert = UIAlertController(title: “Alert”, message: message, preferredStyle: .alert)

alert.addAction(UIAlertAction(title: “OK”, style: .default, handler: nil))

self.present(alert, animated: true, completion: nil)

}

}

What’s happened here? We have added a special requirement to our protocol. Only UIViewController’s can conform to it. Thanks to this, we can call UIViewController methods inside the presentAlert method. This allows us to display the alert.

Let’s go further:

extension UIViewController : AlertPresentable {}

Now, all UIViewControllers have a new ability:

Combining protocols and extensions is helpful for testing too. Guys, how many times have you tried to test a final class from the Android framework or singleton in your app? It’s not a problem for Swift.

Consider this situation and assume we have Swift’s protocol and extension in Kotlin. If you know a method signature, you can create a proper protocol with the same method signature, then create an extension where the final class or singleton implements this protocol and voilà! Instead of using the class directly, you can use your protocol and test it with ease. A code example is worth more than a thousand words, so check this out.

final class FrameworkMap { private FrameworkMap() { … }

public final void drawSomething() { … }

} class MyClass {

…

fun drawSomethingOnMap(map: FrameworkMap) {

map.drawSomething()

}

}

In the test you might want to verify if your drawSomethingOnMap method calls drawSomething on the framework map. It could be hard even with Mockito (a well-known test library for Android). But with a protocol and an extension it will look like this:

protocol Map {

fun drawSomething()

} extension FrameworkMap : Map {}

And then, your drawSomethingOnMap method uses the protocol instead of the class

class MyClass {

…

fun drawSomethingOnMap(map: Map) {

map.drawSomething()

}

}

Sealed classes — Enum on steroids

Lastly, I’d like to bring up the topic of enum.

Nothing has changed between classic Java’s enum and Kotlin’s enum, so I have nothing further to add regarding this issue. But we have something new instead, and it’s a super enum — sealed class. Where did the term “super enum” originate from? Have a look at what Kotlin Docs says:

“ …They are, in a sense, an extension of enum classes: the set of values for an enum type is also restricted, but each enum constant exists only as a single instance, whereas a subclass of a sealed class can have multiple instances which can contain state.”

Ok, cool, they can contain state, but how can we use them?

sealed class OrderStatus {

object AwaitPayment : OrderStatus()

object InProgress : OrderStatus()

object Completed : OrderStatus()

data class Canceled(val reason: String) : OrderStatus()

}

This is a sealed class which models the order status. It looks similar to how we do that with enum, but there is one exception. The Canceled case contains state, which is dependent on reason. There could be many reasons why your order was canceled.

val orderStatus = OrderStatus.Canceled(reason = “No longer in stock”)

…

val orderStatus = OrderStatus.Canceled(reason = “Not paid”)

We can’t do that with enum. Once the enum case is created, it cannot be changed.

Have you noticed any other differences? I used here another feature from sealed class. That is, associated values of different type. Classic enum imposes passing an associated value to all cases, and all values have to be of the same type.

Obviously, there is an equivalent to sealed class in Swift and it’s called… enum. The enum in Kotlin is just a relic of Java, and you will use sealed class 90% of the time. It’s hard to tell apart sealed class from Swift’s enum. They differ only by name and of course sealed class is a reference type, and enum is a value type. Please correct me if I’m wrong.

This is not the end of this topic yet

There is still the important issue of how memory management affects the way we write code (you can read about it in my latest post). I know I didn’t cover all the aspects, and that’s because I’m still learning. If you guys have noticed any other differences between these two great languages, please let me know. I am always eager to learn new things!