本記事の前段についてはこちら
iOSエンジニアのAndroidアプリ開発備忘録 - Qiita
対象読者
備忘録のため、主に自分。
もしくは、iOSアプリを開発(Swift)やってた人で、Kotlin触ってみたいなって人。
本題
Swift やってればだいたい分かるけど、ちょくちょく文法の違いはある。
とりあえずリファレンス読んでおけば事足ります。
僕が開発したての頃とくに「どうやって書くんだっけ?」ってなったところを列挙します。
Playground
まずは触ってみたいと思う人が多いだろうと思う。(僕がそうだったから)
swiftの Playground 相当のものは Kotlin にはないため REPL を使っていた。
- 
Android Studio(+ Kotlin Plugin)が入っている場合
- FindAction(
⌘ + ⇧ + A)からKotlin REPLを選択 
 - FindAction(
 - ターミナルからの場合
- 
brew install kotlinで 入れれば試せる。詳細のインストール方法等はこちら。 - Android Studio も内部ではコマンど叩いてるだけだけだと思う
 
 - 
 
constant, variable
定数、変数の宣言。超初歩的だけど、「初めアレ?」ってなったので。
| Swift | Kotlin | |
|---|---|---|
| constant | let | val | 
| variable | var | var | 
if let
let または run を使用する。
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")
}
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つ !!。
var str: String? = nil
print(str) // nil
print(str!) // "fatal error: unexpectedly found nil while unwrapping an Optional value"
var str: String? = null
print(str) // "null"
print(str!!) // "kotlin.KotlinNullPointerException"
暗黙的アンラップ・Implicitly Unwrapped Optional
等価って考えていいのかな。Late-Initialized Propertiesってのがあります。
(Force Unwrapping した時との例外メッセージが違うので等価ではなさそう。KotlinNullPointerException、 UninitializedPropertyAccessException)
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"
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
func foo(str: String?) {
    guard let str = str else {
        print("str is null")
        return
    }
    print(str.characters.count) // "4"
}
foo(str: "hoge")
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 だよ。
let x = 1
switch x {
    case 1: print("x == 1")
    case 2: print("x == 2")
    default: print("x is neither 1 nor 2")
}
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 書こう。
let a  = 1
let b  = 2
let result = a > b ? "foo" : "bar"
print(result) // "bar"
val a  = 1
val b  = 2
val result = if(a > b) "foo" else "bar"
print(result) // "bar"
構造体・Struct
class に data 修飾子をつける
struct Resolution { var width: Int, height: Int }
let r = Resolution(width: 1, height: 2)
print(r) // "Resolution(width: 1, height: 2)"
data class Resolution(val width: Int, val height: Int){}
val r = Resolution(1, 2)
print(r) // "Resolution(width: 1, height: 2)"
拡張・Extension
- プロパティーの拡張
 
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)
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)
- メソッドの拡張
 
extension Int {
    func repetitions(task: () -> ()) {
        for _ in 0..<self {
            task()
        }
    }
}
3.repetitions {
    print("Hello, Swift!")
}
// "Hello, Swift!"
// "Hello, Swift!"
// "Hello, Swift!"
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 ってのを使う。未だにピンとこない
class MyClass {
    static func foo() -> String {
        return "Hello, Swift!"
    }
    static let bar = "Hello, Swift!"
}
print(MyClass.foo()) // "Hello, Swift!"
print(MyClass.bar) // "Hello, Swift!"
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つだけ。非常に悲しい
let foo = ("left", "right")
print(foo.0) // "left"
print(foo.1) // "right"
val foo = Pair("left", "right")
print(foo.first) // "left"
print(foo.second) // "right"
with, let, apply, run
上記でも紹介したが let 以外に with, let, apply, run などの構文がある。
Swiftにはない構文で比較というわけではないので詳細は省きますが便利です。
詳しくはこちら。
遅延評価
class MyClass {
    lazy var foo = "foo"
}
class MyClass {
    val foo: String by lazy { "foo" }
}
まとめ
他にも annotation や、sealed class などなど紹介しきれていない構文がありますが、また改めて。
まだまだKotlinを始めて数カ月ではありますが、少しでも同じような立場の人の手助けになればと思い書きました。また、何か僕の理解の不十分な箇所や誤りなどあったらご指摘いただけると幸いです。
