iOSエンジニアのAndroidアプリ開発備忘録 - Swift、Kotlinの構文比較編


![iOSエンジニアがAndroidアプリ開発時の備忘録 - Swift、Kotlinの構文比較編.png](https://qiita-image-store.s3.amazonaws.com/0/41522/934a3e8b-4544-d657-ed0f-3ae1fc1c15ef.png "iOSエンジニアがAndroidアプリ開発時の備忘録 - Swift、Kotlinの構文比較編.png")

本記事の前段についてはこちら
[iOSエンジニアのAndroidアプリ開発備忘録 - Qiita](http://qiita.com/RyoAbe/private/f44299bfdb470dcebb8f)

# 対象読者
備忘録のため、主に自分。
もしくは、iOSアプリを開発（Swift）やってた人で、Kotlin触ってみたいなって人。

# 本題
Swift やってればだいたい分かるけど、ちょくちょく文法の違いはある。
とりあえず[リファレンス](https://kotlinlang.org/docs/reference/)読んでおけば事足ります。
僕が開発したての頃とくに「どうやって書くんだっけ？」ってなったところを列挙します。

## Playground
まずは触ってみたいと思う人が多いだろうと思う。（僕がそうだったから）
swiftの Playground 相当のものは Kotlin にはないため REPL を使っていた。

- [Android Studio（+ Kotlin Plugin）](http://crossbridge-lab.hatenablog.com/entry/2015/12/03/220000)が入っている場合
    - FindAction（`⌘ + ⇧ + A`）から `Kotlin REPL` を選択
- ターミナルからの場合
    - `brew install kotlin` で 入れれば試せる。詳細のインストール方法等は[こちら](https://kotlinlang.org/docs/tutorials/command-line.html)。
    - Android Studio も内部ではコマンど叩いてるだけだけだと思う

## constant, variable

定数、変数の宣言。超初歩的だけど、「初めアレ？」ってなったので。

| | Swift | Kotlin |
|:---:|:---:|:---:|
| constant | let | val |
| variable | var | var |


## if let
`let` または `run` を使用する。

```Swift:Swift
var str: String? = "Hello, Swift"
print(str) // "Optional("Hello, Swift")"
print(str!) // "Hello, Swift"
if let str = str {
    print(str) // "Hello, Swift"
} else {
    print("str is nil")
}
```

```Kotlin:Kotlin
var str: String? = "Hello, Kotlin"
print(str) // "Hello, Kotlin"
print(str!!) // "Hello, Kotlin"
str?.let {
    print(it) // "Hello, Kotlin"
} ?: run {
    print("str1 is null")
}
```

## Forced Unwrapping
Kotlin ではエクスクラメーションマーク1つではなく、2つ `!!`。

```Swift:Swift
var str: String? = nil
print(str) // nil
print(str!) // "fatal error: unexpectedly found nil while unwrapping an Optional value"
```

```Kotlin:Kotlin
var str: String? = null
print(str) // "null"
print(str!!) // "kotlin.KotlinNullPointerException"
```

## 暗黙的アンラップ・Implicitly Unwrapped Optional
等価って考えていいのかな。`Late-Initialized Properties`ってのがあります。
（Force Unwrapping した時との例外メッセージが違うので等価ではなさそう。`KotlinNullPointerException`、 `UninitializedPropertyAccessException`）

```Swift:Swift
class MyClass {
    var foo: String!
    var bar: String!
}
val myClass = MyClass()
myClass.foo = "foo"
print(myClass.foo)
print(myClass.bar) // "fatal error: unexpectedly found nil while unwrapping an Optional value"
```

```Kotlin:Kotlin
class MyClass {
    lateinit var foo: String
    lateinit var bar: String
}
val myClass = MyClass()
myClass.foo = "foo"
print(myClass.foo)
print(myClass.bar) // kotlin.UninitializedPropertyAccessException: lateinit property bar has not been initialized
```



## guard

```Swift:Swift
func foo(str: String?) {
    guard let str = str else {
        print("str is null")
        return
    }
    print(str.characters.count) // "4"
}

foo(str: "hoge")
```

```Kotlin:Kotlin
fun foo1(str: String?) {
    if (str == null) {
        print("str is null")
        return
    }
    print(str.length) // "4"。 unwrap しなくて良い。賢い
}
foo1("hoge")

// もしくは、こんな書き方
fun foo2(str: String?) {
	var str = str ?: return
	print(str.length) // "4"
}
foo2("hoge")
```

## Switch
when だよ。

```Swift:Swift
let x = 1
switch x {
    case 1: print("x == 1")
    case 2: print("x == 2")
    default: print("x is neither 1 nor 2")
}
```

```Kotlin:Kotlin
val x = 1
when (x) {
  1 -> print("x == 1")
  2 -> print("x == 2")
  else -> print("x is neither 1 nor 2")
}
```

## 三項演算子・Tertiary Operator
ちゃんと `if` `else` 書こう。

```Swift:Swift
let a  = 1
let b  = 2
let result = a > b ? "foo" : "bar"
print(result) // "bar"
```

```Kotlin:Kotlin
val a  = 1
val b  = 2
val result = if(a > b) "foo" else "bar"
print(result) // "bar"
```

## 構造体・Struct
`class` に `data` 修飾子をつける 

```Swift:Swift
struct Resolution { var width: Int, height: Int }
let r = Resolution(width: 1, height: 2)
print(r) // "Resolution(width: 1, height: 2)"
```

```Kotlin:Kotlin
data class Resolution(val width: Int, val height: Int){}
val r = Resolution(1, 2)
print(r) // "Resolution(width: 1, height: 2)"
```

## 拡張・Extension
- プロパティーの拡張

```Swift:Swift
extension Double {
    var km: Double { return self * 1_000.0 }
    var m: Double { return self }
    var cm: Double { return self / 100.0 }
}
print(25.4.km)
```

```Kotlin:Kotlin
val Double.km: Double get() = this * 1000.0
val Double.m: Double get() = this
val Double.cm: Double get() = this / 100.0
print(25.4.km)
```

- メソッドの拡張

```Swift:Swift
extension Int {
    func repetitions(task: () -> ()) {
        for _ in 0..<self {
            task()
        }
    }
}

3.repetitions {
    print("Hello, Swift!")
}
// "Hello, Swift!"
// "Hello, Swift!"
// "Hello, Swift!"
```

```Kotlin:Kotlin
fun Int.repetitions(task: () -> Unit) {
    for (i in 0 until this) {
        task()
    }
}

3.repetitions {
    println("Hello, Kotlin!")
}
// "Hello, Kotlin!"
// "Hello, Kotlin!"
// "Hello, Kotlin!"
```

## 静的・Static
`companion object` ってのを使う。未だにピンとこない

```Swift:Swift
class MyClass {
    static func foo() -> String {
        return "Hello, Swift!"
    }
    static let bar = "Hello, Swift!"
}
print(MyClass.foo()) // "Hello, Swift!"
print(MyClass.bar) // "Hello, Swift!"
```

```Kotlin:Kotlin
class MyClass {
	companion object {
		fun foo() {
			print("Hello, Kotlin!")
		}
		val bar = "Hello, Kotlin!"
	}
}
print(MyClass.foo()) // "Hello, Kotlin!"
print(MyClass.bar) // "Hello, Kotlin!"
```

## タプル
Kotlinにはない。Pairならある。2つだけ。非常に悲しい

```Swift:Swift
let foo = ("left", "right")
print(foo.0) // "left"
print(foo.1) // "right"
```

```Kotlin:Kotlin
val foo = Pair("left", "right")
print(foo.first) // "left"
print(foo.second) // "right"
```

## with, let, apply, run
上記でも紹介したが `let` 以外に `with, let, apply, run` などの構文がある。
Swiftにはない構文で比較というわけではないので詳細は省きますが便利です。
詳しくは[こちら](http://qiita.com/ngsw_taro/items/d29e3080d9fc8a38691e)。

## 遅延評価

```Swift:Swift
class MyClass {
    lazy var foo = "foo"
}
```

```Kotlin:Kotlin
class MyClass {
    val foo: String by lazy { "foo" }
}
```


# まとめ
他にも [annotation](https://kotlinlang.org/docs/reference/annotations.html) や、[sealed class](https://kotlinlang.org/docs/reference/classes.html) などなど紹介しきれていない構文がありますが、また改めて。

まだまだKotlinを始めて数カ月ではありますが、少しでも同じような立場の人の手助けになればと思い書きました。また、何か僕の理解の不十分な箇所や誤りなどあったらご指摘いただけると幸いです。

続きは、[Xcode、Android Studio 比較編](http://qiita.com/RyoAbe/items/26d173b8145c15f146dd)