Kotlin文法 - 基本


# はじめに

[Kotlin Reference](https://kotlinlang.org/docs/reference/)の日本語訳。複数の記事に分けていて、この記事はBasic章に相当する。

一気にざっと文法全体を確認したい場合は「[３０分で覚えるKotlin文法](http://qiita.com/k5n/items/cc0377b75d8537ef8a85)」を用意したのでそちらをどうぞ。

英語をそのまま訳したものはどうしても分かりにくくなりがち。ここでは公式リファレンスそのままにこだわってなくて、内容を理解した上で適宜表現を変えたり補足したり省略したりしている。

他の人の記事で「[Kotlinの公式リファレンスを日本語化してみた[前編]](http://qiita.com/dogwood008/items/6e8d3225ea9bb0fe3099)」っていうのもあって、最初のGetting Started章から訳されてる。

# 目次

複数の記事に分けているのでここに全体像のリンクを貼っておく。

 - 基本 （この記事）
 - クラスとオブジェクト
     - [クラス、継承、プロパティ](http://qiita.com/k5n/items/35e76d79ee9de4effb89)
     - [インターフェース、アクセス修飾子、拡張](http://qiita.com/k5n/items/98332a406ddb9170217c)
     - [データクラス, ジェネリクス](http://qiita.com/k5n/items/18adb5c3503a54e96c22)
     - [ネストされたクラス、Enumクラス、オブジェクト、委譲、委譲されたプロパティ](http://qiita.com/k5n/items/57d362295c2299090d8d)
 - [関数とラムダ](http://qiita.com/k5n/items/964d765767a65cc3de5b)
 - その他
     - [分解宣言、範囲、型チェックとキャスト](http://qiita.com/k5n/items/c8bf7a507b64f20eebd0)
     - [this、等価性、演算子オーバーロード、Null安全、例外](http://qiita.com/k5n/items/6fe586bf2e5530684681)
     -  [アノテーション、リフレクション、型安全なビルダー、動的型](http://qiita.com/k5n/items/3eaafc5aa5a07cd02f5c)
 - [Javaとの相互運用](http://qiita.com/k5n/items/ceb1f921b27d62fc9fcb)

# Nullableについて

この章より後で説明される *Nullable* というのが説明に出てくる。Kotlinでは変数に *null* は入れられないので、*null* か参照を入れられる特別な *Nullable* というものが用意されている。

*Int* の参照か *null* が入れられる *Nullable* は *Int?* と記述する。その他の構文は後ほど。構文も含めてSwiftでのOptionalと同様のもの。

# 基本型

Kotlinでは全てがプロパティやメソッドを持つオブジェクト。実際には速度的な観点からビルトイン型もあるが、それらも利用者からは普通のクラスのように見える。

## 数値

数値の扱いはJavaに近いが全く同じではない。数値は暗黙の型変換が行われず、記法も少し違う場合がある。

| 型 | ビット数 |
|:---|:----------|
| Double | 64 |
| Float | 32 |
| Long | 64 |
| Int | 32 |
| Short | 16 |
| Byte | 8 |

### 数値定数

 - １０進数: 123
   - Longなら後ろにLをつける: 123L
 - １６進数: 0x0F
 - ２進数: 0b00001011
 
 （８進数はサポートされていない）
 
 - デフォルトではDouble: 123.5, 123.5e10
 - Floatは後ろにfかFをつける: 123.5f

### 表現

*Int?* などの__Nullable__やジェネリクスでは、数値はboxingされる。

```kotlin
val a: Int = 10000 // これはJVMのプリミティブ型として格納される
print(a === a) // 'true'と表示される
val boxedA: Int? = a    // boxingされる
val anotherBoxedA: Int? = a // boxingされる
print(boxedA === anotherBoxedA) // !!!'false'と表示される!!!
// 内部の値の等価性は保持される
print(boxedA == anotherBoxedA) // 'true'と表示される
```

（注: ===は参照の等価性, ==は構造の等価性の比較。つまり==はJavaでいうequalsメソッドによる比較。）

### 明示的な型変換

小さい型は大きい型のサブ型ってわけじゃない。もしそうならこんな感じで問題が発生する。

```kotlin
// もし〜だったら的な仮想コード。コンパイルできない。
val a: Int? = 1 // Int (java.lang.Integer)にBoxingされる
val b: Long? = a // 暗黙変換で Long (java.lang.Long)にBoxingされる
print(a == b) // ちょwwwこいつ"false"とか言うwww
// Longのequals()がもう一方の型もLongかチェックするからなんですね〜
```

そんなわけで__小さい型は大きい方に暗黙的に変換されない__。

```kotlin
// 1はIntだけど変数型がByteなのでコンパイル時にByte型の数値として扱われる
val b: Byte = 1 // OK, 数値は静的にチェックされる
// Byte型の値をInt型に格納しても暗黙型変換はされない
val i: Int = b // ERROR
```

```kotlin
val i: Int = b.toInt() // OK: 明示的に型変換
```

全ての数値型は次の型変換メソッドを持っている。

 - toByte(): Byte
 - toShort(): Short
 - toInt(): Int
 - toLong(): Long
 - toFloat(): Float
 - toDouble(): Double
 - toChar(): Char

暗黙の型変換がないことは型推論と算術演算子のオーバーロードによりほとんど気にならない。

```kotlin
// a + b では a.plus(b) が呼ばれる。LongがIntを受け取るplusメソッドを用意している。
val l = 1L + 3 // Long + Int => Long
```

### 演算子

数値に対して標準的な算術演算子が利用できる。演算子は実際には適切なクラスのメンバが呼び出される[^2]。詳細は演算子オーバーロードの章で説明する。

[^2]: コンパイラが最適化のために対応する命令に書き下すことはある。

ビット演算には特別な記号は割り当てられていないが、次のように挿入形式で使える関数がある。

```kotlin
// shlは算術左シフトを行う
val x = (1 shl 2) and 0x000FF000
```

IntとLongには以下のビット演算がある。

 - shl(bits) – 符号付左シフト (Javaの <<)
 - shr(bits) – 符号付右シフト (Javaの >>)
 - ushr(bits) – 符号なし右シフト (Javaの >>>)
 - and(bits) – ビットAND
 - or(bits) – ビットOR
 - xor(bits) – ビットXOR
 - inv() – ビット反転

## 文字

文字型はChar、もうわかってると思うけど暗黙の型変換はない。

```kotlin
fun check(c: Char) {
  if (c == 1) { // ERROR: 暗黙の型変換
    // ...
  }
}
```

リテラルはシングルクォートで囲む '1', '\n', '\uFF00' みたいに。明示的にInt型に変換できる。

```kotlin
fun decimalDigitValue(c: Char): Int {
  if (c !in '0'..'9')
    throw IllegalArgumentException("Out of range")
  return c.toInt() - '0'.toInt() // 明示的に数値に変換
}
```

数値と同様に *Nullable* ではBoxingされる。

## 真偽値

*Boolean* は *true* か *false* を取る。*Nullable* ではBoxingされる。３つの組み込み演算子 * ||, && , !* がある。

## 配列

Arrayクラスで表される。get/setメソッドがあり（[]でアクセスできる）、sizeを持ち、他に幾つかの便利メソッドを持つ。

```kotlin
class Array<T> private constructor() {
  val size: Int
  fun get(index: Int): T
  fun set(index: Int, value: T): Unit

  fun iterator(): Iterator<T>
  // ...
}
```

```kotlin
// [1, 2, 3]を作る
val list = arrayOf(1, 2, 3)
// nullで埋められたサイズ3の配列を作る
var arr: Array<Int?> = arrayOfNulls(3)
// Array<String>型で値が ["0", "1", "4", "9", "16"]の配列を作る
val asc = Array(5, { i -> (i * i).toString() })
```

注: Javaと違って *Array&lt;String&gt;* 型を *Array&lt;Any&gt;* 型に代入はできない[^3]。これは実行時エラーの発生を防いでくれる。（ただし *Array&lt;out Any&gt;* を利用できる。Type Projectionの章を参照。）

[^3]: 元の文章ではinvariantと記載されている。これは[共変性と反変性](https://ja.wikipedia.org/wiki/共変性と反変性_(計算機科学))の説明によるところのinvariantということ。

Boxingのオーバーヘッドを生じないプリミティブ型の配列を表す特別なクラスを用意している。ByteArray, ShortArray, IntArrayなど。これらはArrayを継承してはいないが、同じプロパティとメソッドを持っている。これらも対応するファクトリ関数を持っている。

```kotlin
// プリミティブ型の配列である IntArray を用いる
val x: IntArray = intArrayOf(1, 2, 3)  // 型を明示したが、推論してくれるので省略可能
x[0] = x[1] + x[2]
```

## 文字列

文字列はString型で表され、immutable（中身が変更不可）である。構成要素は文字であり、s[i]という形でインデックスを指定してアクセスできる。forループでイテレートできる。

```kotlin
for (c in str) {
  println(c)
}
```

### 文字列リテラル

```kotlin
// Javaの文字列と同じ感じのやつ
val s = "Hello, world!\n"

// トリプルクォートを使うとスケープが効かない生文字列になる
val text = """
  for (c in "foo")
    print(c)
"""
```

### 文字列テンプレート

$を使って文字列の中に変数の値や計算結果を埋め込める。

```kotlin
val i = 10
val s = "i = $i" // i = 10

val s = "abc"
val str = "$s.length is ${s.length}" // abc.length is 3

// $そのものを表現するには
val price = "${'$'}9.99" // $9.99
```
# パッケージ

```kotlin
// 所属するパッケージ名を指定
package foo.bar

// フルネームはfoo.bar.baz
fun baz() {}

// フルネームはfoo.bar.Goo
class Goo {}

// ...
```

## インポート

```kotlin
import foo.Bar // これでBarにアクセスできる
```

```kotlin
import foo.* // fooの下にあるものが全てアクセスできる
```

```kotlin
import foo.Bar // Barにアクセスできる
import bar.Bar as bBar // bBarは'bar.Bar'を表す
```

クラス以外にも以下をimportできる。

 - トップレベルの関数やプロパティ
 - object宣言の中の関数やプロパティ
 - enum定数

Javaと違って特別に"import static"というのはない。通常のimportでいける。

# 制御構文

## if

Kotlinではifは式であり戻り値を返せる。なので三項演算子は必要ないので存在しない。

```kotlin
// 伝統的な使い方
var max = a 
if (a < b) 
  max = b 
 
// else付き
var max: Int
if (a > b) 
  max = a 
else 
  max = b 
 
// ifが式であることを利用した三項演算子的使い方
val max = if (a > b) a else b
```

分岐はブロックにできる。最後の行の式の評価結果がブロックの値になる。

```kotlin
val max = if (a > b) { 
    print("Choose a") 
    a 
  } 
  else { 
    print("Choose b") 
    b 
  }
```

ifの結果を利用するならelse節が必要になる。

## when

whenはC系言語でいうswitchの置き換え。

```kotlin
when (x) {
  1 -> print("x == 1")
  2 -> print("x == 2")
  // どれにも当てはまらないならelseが実行される
  else -> { // ブロックも使える
    print("x is neither 1 nor 2")
  }
}
```

whenも式として値を返せる。その場合else節は必須で、全ての分岐が値を返す必要がある。ブロックが複数行ならifと同様に最後に評価された値を返す。

```kotlin
when (x) {
  // 0と1で同じ処理なら、コンマで結合できる
  0, 1 -> print("x == 0 or x == 1")
  else -> print("otherwise")
}
```

```kotlin
when (x) {
  // 定数でなくてもマッチさせられる
  parseInt(s) -> print("s encodes x")
  else -> print("s does not encode x")
}
```

```kotlin
when (x) {
  // 範囲に含まれるか
  in 1..10 -> print("x is in the range")
  // 配列などのコレクションに含まれるか
  in validNumbers -> print("x is valid")
  // 否定も使える。範囲に含まれなければ実行される。
  !in 10..20 -> print("x is outside the range")
  else -> print("none of the above")
}
```

```kotlin
val hasPrefix = when(x) {
  // 型チェックもできる。チェック後は自動的にキャストされる。
  is String -> x.startsWith("prefix") // xはStringとして扱える
  else -> false
}
```

whenに引数を与えないと、ifの代わりに利用できる。各条件は単純に真偽値判定される。

```kotlin
when {
  x.isOdd() -> print("x is odd")
  x.isEven() -> print("x is even")
  else -> print("x is funny")
}
```

## for

```kotlin
// まぁこれは説明いらないよね
for (item in collection)
  print(item)
  
// もちろんボディはブロックにできる
for (item: Int in ints) {
  // ...
}
```

*for* はイテレータを提供するものなら何でもイテレートできる。すなわち、

 - メンバーまたは拡張として *iterator()* を持ち、その戻り値の型が
  - メンバーまたは拡張として *next()* を持ち、かつ
  - メンバーまたは拡張として *Boolean* を返す *hasNext()* を持つ

これら３つ全ての関数は *operator* としてマークされている必要がある。

インデックス付きにしたいなら

```kotlin
// 最適化によってindicesは実際にはオブジェクトを生成しないのでパフォーマンス劣化はない
for (i in array.indices)
  print(array[i])
  
// withIndex()でインデックスと値のペアで回すこともできる
for ((index, value) in array.withIndex()) {
    println("the element at $index is $value")
}
```

## while

while, do-whileは普通。

```kotlin
while (x > 0) {
  x--
}

do {
  val y = retrieveData()
} while (y != null) // ここでyが見える！
```

# リターンとジャンプ

３つのジャンプ命令がある。

 - *return* : デフォルトでは直近の（無名を含む）関数を抜ける。注：ラムダは違う。
 - *break* : 直近のループを抜ける
 - *continue* : 直近のループの次のステップに進む

 
## break, continueとラベル 

```kotlin
// ラベルを使って直近でなく指定ラベルのループを抜ける
loop@ for (i in 1..100) {
  for (j in 1..100) {
    if (...)
      break@loop
  }
}
```

## returnとラベル

*return* は直近の関数を抜ける。ラムダじゃない。

```kotlin
fun foo() {
  ints.forEach {
    if (it == 0) return // これはforEachでなくfooを抜ける
    print(it)
  }
}
```

もしラムダを抜けたいならラベルを使う。

```kotlin
fun foo() {
  ints.forEach lit@ {
    if (it == 0) return@lit
    print(it)
  }
}
```

この程度でラベルを定義する必要はなく、暗黙のラベル（ラムダが渡される関数の名前）を使った方が便利。

```kotlin
fun foo() {
  ints.forEach {
    if (it == 0) return@forEach // foo関数ではなくforEachに渡したラムダを抜ける（処理１回分）
    print(it)
  }
}
```

またはラムダじゃなく無名関数を渡す。

```kotlin
fun foo() {
  ints.forEach(fun(value: Int) {
    if (value == 0) return // foo関数ではなくforEachに渡した無名関数を抜ける（処理１回分）
    print(value)
  })
}
```

ラベルを使いつつ値を返したいならこう書く。

```kotlin
return@a 1
```

# 次の章へ

次は[Kotlin文法 - クラス、継承、プロパティ](http://qiita.com/k5n/items/35e76d79ee9de4effb89)へGO!