Swift vs Kotlin
Tags: swift
Published: 2022-07-18 01:23:20

This article is aiming to help an Android developer get a quick knowledge of the Swift programming language. (Writing from this perspective.)

I didn’t mean to write a very long and detailed article to cover everything, just a quick one to get you onboarded.

This article is also suitable for:

- Experienced programmer (who knows other programming languages) wants to learn Swift.
- iOS developer (who knows Swift) wants to learn Kotlin.
- iOS beginner developers.
- Developer hasn’t used Swift for a while and wants to get a quick refresher memo.

## Basic types

| Swift | Kotlin |
| --- | --- |
| Bool | Boolean |
| Array | Array, List, MutableList |
| Set | Set |
| Dictionary | Map |

Other types are basically the same.


## Syntax

|  | Swift | Kotlin |
| --- | --- | --- |
| variables (not totally equals, see elaboration below) | let/var | val/var |
| named arguments | at: 0 | at = 0 |
| function | func name() → returnType | fun name(): returnType |
| absence of a value | nil | null |
| unwrapped type | String! | - |
| if | if number != nil | if(number != null) |
| provide default value if nil or null | xxx ?? “default string” | ? : ”default string” |
| if it has value, do {} | if let number = Int(”333”) {} | ?.let {} |
| for loop | for i in 1...5 {} | for (i in 1..5) {} |
| for loop | for i in 1..<5 {} | for (i in 1 until 5) {} |
| do while loop | repeat {} while | do {} while () |
| this instance | self | this |
| value object | struct | data class |
|  | as? | as? |
|  | as! | as |
|  | try? | - |
|  | try! | - |
| class initializer | initializer | constructor |
| init a mutable list | var someInts: [Int] = [] | val someInts = mutableListOf<Int>() |
| init a empty dictionary/map | var namesOfIntegers: [Int: String] = [:] | val namesOfIntegers = mutableMapOf<Int, String>() |

### Constants and Variables

Swift:

- `let` you can not assign value again. If the type is struct, you can not update any var properties of the instance. (If it's a class, then you can update var properties).
- `var` can both assign values or update properties of the instance.
- `var` also makes an array mutable.

Kotlin:

- `val` means final in java, you can not assign values again, but you can update the public vars of the instance.
- `var` means you can assign values again.
- collections types’ immutable or mutable are controlled by the data type.

### Switch case

Swift:

```swift
var x = 3
switch x {
    case 1: print("x == 1")
    case 2, 4: print("x == 2 or x == 4")
    default: print("x is something else")  
}
```

Kotlin:

```kotlin
val x = 3
when (x) {
    1 -> print("x == 1")
    2, 4 -> print("x == 2 or x == 4")
    else -> print("x is something else")
}
```

### String interpolation

Swift:

```swift
var name = "Mike"
print("Hello \(name)")
```

The string can also be output in a format:
```swift
let str = NSString(format:"%d , %f, %ld, %@", 1, 1.5, 100, "Hello World")
print(str)
```

Kotlin:

```kotlin
var name = "Mike"
println("Hello $name")

val str = String.format("%d, %f, %d, %s", 1, 1.5, 100, "Hello World")
print(str)
```

## Function and Closure

The Swift function has an argument label:

```swift
func someFunction(argumentLabel parameterName: Int) {
    // In the function body, parameterName refers to the argument value
    // for that parameter.
}
```

while `parameterName` is used inside the function, `argumentLabel` is used by the caller.

When an argument label is not provided, parameterName also plays the role of argumentLabel.

If you don't want to specify an argument label at all, the argument label can be omitted by using underscored `_`.

### Closure

Closure is similar to lambda in Kotlin.

A simple Swift example:

```swift
let sayHello = { (name: String) -> String in
    let result = "Hello \(name)"
    print(result)
    return result
}

sayHello("Mike")
```

Do the same thing in Kotlin:

```kotlin
val sayHello : (String) -> String = { name: String -> 
    val result = "Hello $name"
    print(result)
    result
}

sayHello("Mike")
```

Common:

- The type can be inferred from the context.
- Can be passed as arguments as another function’s parameter to achieve nested functions (high-order functions).
- if the closure/lambda is the last parameter, we can put it outside the function’s parentheses. if it’s the only parameter, we don’t need to write parentheses().

Differences:

- In Swift, only single expression closure can omitting the `return`
  keyword; In Kotlin, the last expression will be treated as the return value, no return keyword in lambda.
- Swift has shorthand argument names such as `$0`, `$1`, `$2`.

## Custom types

| Swift | Kotlin |
| --- | --- |
| class | class |
| protocol | interface |
| extension | extension methods |

### class
The class of Swift and Kotlin looks quite the same.

The inheritance is using `:` and the subclass function could `override` the super class's function.

There is an order requirement: the class need to be put before any protocols.

The only thing different is the constructor, in swift it’s initializer:

```swift
class Person {
    let name: String
    init(name: String = "") {
        self.name = name
    }
}
let p1 = Person()
print("\(p1.name)") // default name: ""

let p2 = Person(name: "haha")
print("\(p2.name)")
```

In Kotlin, we could achieve the same result by writing like this:

```kotlin
class Person(val name: String = "") {
}
val p1 = Person()
print("${p1.name}") // default name: ""

val p2 = Person(name="haha")
print("${p2.name}")
```

### struct
Struct is value type.

struct vs class:

- class can inherit.
- struct is value type, copies never share data; class is reference type, all copies will share the same instance.
- class has `deinit`.
- class instance can be `let` , and you can change the `var` property of the class.

```swift
class Person {
    var name = "Lily"
}

let p1 = Person()
p1.name = "Justin"

print("\(p1.name)")
```

This is ok.

But if Person is a struct:

```swift
struct Person {
    var name = "Lily"
}

let p1 = Person()
p1.name = "Justin"
// Compiler error: Cannot assign to property: `p1` is a `let` constant
```

When using struct, we have to use `**var** p1 = Person()`.

### protocol
protocol is just like `interface` in Kotlin.

We could define function and properties as contracts.

The properties could be:
```swift
protocol SomeProtocol {
    var mustBeSettable: Int { get set }
    var doesNotNeedToBeSettable: Int { get }
}
```

There are slight differences in protocol and interface, like the class implementing the protocol doesn’t need to use the `override` keyword on functions.

### extension
extension is also different. In Swift, extension is more like a place to hold the functions and properties.

```swift
extension String {
    func trimmed() -> String {
        self.trimmingCharacters(in: .whitespacesAndNewlines)
    }
    
    mutating func trim() {
        self = self.trimmed()
    }
    
    var lines: [String] {
        self.components(separatedBy: .newlines)
    }
}
```

In Kotlin the extension method could be the top level method, just add the type before `.`:

```kotlin
fun String.someMethod() : String {
    return this.trim()
}
```

### enum

Swift enum:

```swift
enum CompassPoint {
    case north
    case south
    case east
    case west
}
```

Multiple cases can be put in one line, separated by comma:

```swift
enum Planet {
    case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
}
```

When using the enum, we can drop the type using a shorter dot syntax:

```swift
var directionToHead = CompassPoint.west
directionToHead = .east
```
Swift enum has an `allCases` property, which exposes a collection of all the cases.

Kotlin:

```kotlin
enum class Direction {
    NORTH, SOUTH, WEST, EAST
}
```

In enum we can also define properties and functions, which is the same for Swift and Kotlin.

## Optionals

While the syntax of Swift’s optional type and Kotlin’s nullable type looks similar (a question mark following the type), they are different.

Swift’s optional type is more like Java’s `Optional`.

You will always need to unwrap it before using the value.

```swift
var someString : String? = nil
print(someString?.count) // print nil
print(someString!.count) // Fatal error: Unexpectedly found nil while unwrapping an Optional value
```

When the variable has value, we want to use it:

```swift
var someString : String? = "Hello"

if (someString != nil) {
    print("\(someString) with length \(someString?.count)")
    // print: Optional("Hello") with length Optional(5)
    
    print("\(someString!) with length \(someString!.count)")
    // print: Hello with length 5
}
```

Note that when used directly, the variable will always be an Optional.

Actually in Swift there is a simpler way to do this, using `if let`:

```swift
if let someStringValue = someString {
    print("\(someStringValue) with length \(someStringValue.count)")
}
```

The `someStringValue` is the unwrapped value from `someString`, and the block is only entered when it's not `nil`.

In Kotlin:

```kotlin
var someString : String? = null
print(someString?.length) // print null
print(someString!!.length) // NullPointerException
```

The difference is mainly when the variable has value:

```kotlin
var someString : String? = "Hello"
if(someString != null) {
   print("$someString with length: ${someString.length}")  
}
// print: Hello with length: 5
```

In Kotlin, after we check the variable is not null, we could use the value directly, in the following code inside `{}` , the compiler knows the variable is not null.

### If let and guard let

As we see in the above sample in the Optional section, the `if let` can unwrap the Optional value, and only execute the block when it has value.

The `guard let` does the opposite: the `else` block will be entered only when the value is `nil` .

```swift
func printSquare(of number: Int?){
    guard let number = number else {
        print("Oops we got nil")
        return
    }
    
    print("\(number) * \(number) is \(number * number)")
}
```

guard let can be used to do the argument checking and early return.

After the guard, the number is no longer optional, it has value.


## Last note

I won’t suggest spending much time to learn a language syntax in every detail.

Just grab some basics and you are ready to go, you will explore more on your daily work.

Anyway, I hope this article is handy and useful to you.

## References

- Swift book: [https://docs.swift.org/swift-book/](https://docs.swift.org/swift-book/)