A Comparison of Swift and Kotlin Languages
This article focuses on the main similarities and differences between Swift and Kotlin, including implementation, style, syntax and other important details. By Aaqib Hussain.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
A Comparison of Swift and Kotlin Languages
30 mins
- Understanding Similarities Between Swift and Kotlin
- Declaring Properties
- Kotlin — Mutable Properties
- Swift – Mutable Properties
- Kotlin — Immutable Properties
- Swift — Immutable Properties
- Data Structures
- Arrays
- Dictionaries / Maps
- Functions
- Lambda Functions / Closures
- Nullable / Optional Types
- Handling a Nullable / Optional Type
- Control Flow
- Classes
- Class Extensions
- Interface / Protocol
- Functional Programming Tools
- Understanding Differences Between Swift and Kotlin
- Where to Go From Here?
Control Flow
Just as functions and closures are the building blocks of any app, if-else
, switch
, for
loops and other types of control flow are the logical glue that enable applications to work.
Kotlin — if-else
If-else
statements work in Kotlin similar to most other languages:
if (a > b) {
println("Choose a")
} else {
println("Choose b")
}
Swift — if-else
One cool feature in Swift is that parentheses ()
around the condition are also optional. I’m just wondering how long it will take for Kotlin to adopt this feature. ;]
if a > b {
print("Choose a")
} else {
print("Choose b")
}
Kotlin — when
when
is the name given to switch
statements in Kotlin.
val x = 3
when (x) {
1 -> println("x == 1")
2 -> println("x == 2")
else -> {
print("x is neither 1 nor 2")
}
}
Swift – switch
let x = 3
switch x {
case 1:
print("x == 1")
case 2:
print("x == 2")
default:
print("x is neither 1 nor 2")
}
Note that in Swift, a switch
statement must be exhaustive. In other words, a default clause is required if every single possible value of the condition hasn’t been tested. This is not the case in Kotlin; so for switch
statements Swift is actually more clear and less prone to programmer errors. On the other hand, the syntax for switch
statements in Kotlin is more concise. In both languages, the statement returns as soon as the first matching condition is evaluated, so there is no need for a break
statement.
Kotlin — for loop
There are a number of ways of writing loops in Kotlin.
val days = arrayOf("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun")
for (day in days) {
println(day)
}
for
loop using the range operator:
for (item in 1..10) {
println(item)
}
In this example the ..
specifies an inclusive range; the numbers 1 – 10 are printed. Both Kotlin and Swift provide a variety of different types of range operators.
Swift – for loop
let days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
for day in days {
print(day)
}
Using another type of range operator, in Swift:
for item in 1..<10 {
print(item)
}
Classes
Declaring a class in both languages is almost the same:
Kotlin - Class
class MainActivity: AppCompatActivity() {
}
Swift - Class
class ViewController: UIViewController {
}
What are known as "constructors" in Kotlin are "initializers" in Swift. Kotlin also has an init
block that is paired with a constructor.
Kotlin - Constructor
class Car constructor(_model: String) {
val model: String
init {
model = _model
}
}
Swift - Initializer
public class Car {
let model: String
init(model: String) {
self.model = model
}
}
Class Extensions
Class extensions are a cool feature adopted by modern languages. It helps in extending the functionality of existing classes.
Kotlin - Extension
Consider extending the Int
class with a function that returns a square of an integer:
fun Int.square(): Int {
return this * this
}
println(5.square()) //prints 25
Swift - Extension
extension Int {
func square() -> Int {
return self * self
}
}
print(5.square()) //prints 25
Interface / Protocol
What is known as an interface in Kotlin, and other languages, is called a protocol in Swift. It helps you maintain a decoupled codebase, achieve polymorphism, and write mocks for testing.
Kotlin — Interface
In Kotlin an interface declaration looks just like the declaration of a class:
interface Animal {
var canFly: Boolean
fun eat()
fun makeSound()
}
Swift - Protocol
protocol Animal {
var canFly: Bool {get}
func eat()
func makeSound()
}
An interface / protocol can also have a default implementation. Default behavior remains the same whenever that function is called without being overridden. Assume you want the property canFly
to be false
in all conditions until or unless its required to change.
Kotlin - Default Implementation
interface Animal {
val canFly: Boolean
get() = true
}
Swift — Default Implementation
Extensions are used to give protocols default implementations:
protocol Animal {
var canFly: Bool {get}
}
extension Animal {
var canFly: Bool {
return false
}
}
Functional Programming Tools
These new languages come packed with powerful tools that enable you to write code using a functional paradigm. There are lots of tools provided by them, but have a look at just a few of them.
map
map
is used for transforming data into a new form.
Kotlin - map
Consider a data class
Person, containing properties name and date of birth.
data class Person(var name: String, var dob: String)
Note: In Kotlin a Data Class is similar to a class, but with the sole purpose of holding data. It makes your code more concise and you don't have to write an initializer. Data classes are a powerful way in Kotlin to implement "value objects".
Note: In Kotlin a Data Class is similar to a class, but with the sole purpose of holding data. It makes your code more concise and you don't have to write an initializer. Data classes are a powerful way in Kotlin to implement "value objects".
Now, consider a list containing few objects of type Person:
val persons = listOf(Person("Jon", "12 August"),
Person("Kim", "10 July"),
Person("Vanessa", "12 August"),
Person("Alisa", "26 March"), null)
You might be wondering why I assigned a null
to the end of the list? Assigning a list with a null is not required. Sit tight! you'll have your answer soon enough. :]
Say you want to get the names of all the persons into a separate list — that's where you'll use the map
function to help you.
val names = persons.map { it?.name } //Jon, Kim, Vanessa, Alisa, null
Swift — map
Similarly, in Swift consider a Person struct
:
struct Person {
let name: String
let dob: String
init(name: String, dob: String) {
self.name = name
self.dob = dob
}
}
And an array of persons:
let persons = [Person(name: "Jon", dob: "12 August"),
Person(name: "Kim", dob: "10 July"),
Person(name: "Vanessa", dob: "12 August"),
Person(name: "Alisa", dob: "26 March"), nil]
To transform the persons array into a names array:
let names = persons.map { $0?.name } //Jon, Kim, Vanessa, Alisa, nil
filterNotNull & compactMap
To remove null
/ nil
objects from an array:
Kotlin - filterNotNull
//returns List<Person> instead of List<Person?>
val nonNullPersons = persons.filterNotNull()
Swift - compactMap
compactMap
is similar to the map
function, but it returns all the non-nil objects.
//returns [Person] instead of [Person?]
let nonNullPersons = persons.compactMap{$0}
Filter
Instead of iterating through an array or list with a loop, the filter function can be used to filter for the desired values.
Filter the array having the date of birth as "12 August."
Kotlin - filter
val personWithSameDOB = persons.filter { it?.dob == "12 August" }
Swift - filter
let personWithSameDOB = persons.filter { $0?.dob == "12 August" }