Kotlinのチュートリアルをやってみた②

前回に引き続きSwiftエンジニアがKotlinのチュートリアルを進めます。今回はKotlin Koans onlineの教材を見つつ、手元で実装してみます。online教材の左上を見るとExamplesというのがあるので、その中のHello, world!の章について今回は試してみようと思います。
http://try.kotlinlang.org/#/Examples/Hello,%20world!/Simplest%20version/Simplest%20version.kt

# 自分が実装した分のリポジトリ

https://github.com/akatsuki174/KotlinTutorial
上記のHelloWorld.ktファイル

# Hello, world!

## Simplest version

最もシンプルなHello Worldの出し方です。

```kotlin
fun SimplestVersion() {
    println("Hello, World!")
}
```

プログラムとしては短いですが、このプログラムからいくつかのことがわかります。

* メソッドを宣言する時は`fun`を用いる
* 「;」はあってもなくても大丈夫
* メソッドは必ずしもクラスに属さない（グローバル関数のような形で書ける）

また、いろいろいじって調べる上で以下のことがわかりました。

* 同じクラスのメソッドを呼ぶ時にselfやthisなどを付けずに書ける
* アクセス修飾子のデフォルト値はpublic
  * Javaの場合はデフォルトだと同じパッケージ内のクラスから利用可能

## Reading a name from the command line

文字列や配列の扱い方を学びます。

```kotlin
fun main(args: Array<String>) {
    if (args.size == 0) {
        println("Please provide a name as a command-line argument")
        return
    }
    println("Hello, ${args[0]}!")
}
```

### 文字列の扱い

Stringの中で変数の式展開をするには`${[変数]}`を使うか`$[変数]`を使うことになります。以下の公式の例を見て使い分けの感覚をつかむと良さそうです。

```kotlin
val s = "abc"
val str = "$s.length is ${s.length}" // -> abc.length is 3
```

トリプルクォートを使うと改行やインデントもそのまま代入できるようです。

```kotlin
val text = """
  for (c in "foo")
    print(c)
"""
println("$text")
// 出力は以下の通り
//  for (c in "foo")
//    print(c)
```

```kotlin
val price = "$\n9.99"
println("$price")
// 出力は以下の通り
//$
//9.99

val price = """$\n9.99"""
println("$price")
// 出力は以下の通り
//$\n9.99
```

### argsへの入力方法

IntelliJ IDEAを使ってargsに値を渡す方法は以下の通りです。
■⌘ + alt + rを押す
![スクリーンショット 2017-04-13 23.27.00.png](https://qiita-image-store.s3.amazonaws.com/0/100736/c80387e1-4109-d325-ad82-4cd4ffc7aea2.png)
■eを入力
![スクリーンショット 2017-04-13 23.27.13.png](https://qiita-image-store.s3.amazonaws.com/0/100736/ed687097-3763-26c0-d59c-f10fe9eee321.png)
■Edit Configurationsが選択されているのでEnter
■ConfigurationタブのProgram argumentsに入力
![スクリーンショット 2017-04-13 23.27.22.png](https://qiita-image-store.s3.amazonaws.com/0/100736/6edab6d9-d18c-0b85-699c-0ef36b61fc5d.png)

## Reading many names from the command line

ここではループが出てきます。

```kotlin
fun readingManyNamesFromTheCommandLine(args: Array<String>) {
    for (name in args)
        println("Hello, $name!")
}
```

もちろんブロックを用いて書くこともできます。

```kotlin
for (name in args) {
    println("Hello, $name!")
}
```

インデクスを使用したい場合はこのような書き方もできます。

```kotlin
for (i in args.indices)
    println("Hello, ${args[i]}!")
```

```kotlin
for ((index, value) in args.withIndex())
    println("$index: Hello, $value!")
```

## A multi-language Hello

if式、when式が出てきました。

```kotlin
fun aMultiLanguageHello(args: Array<String>) {
    val language = if (args.size == 0) "EN" else args[0]
    println(when (language) {
        "EN" -> "Hello!"
        "FR" -> "Salut!"
        "IT" -> "Ciao!"
        else -> "Sorry, I can't greet you in $language yet"
    })
}
```

### if式

Kotlinではifは式なので、三項演算子と同じような書き方をすることができます。

```kotlin
// Kotlinでifを使って書いた場合
val language = if (args.size == 0) "EN" else args[0]

// Swiftで三項演算子を使って書いた場合
let language = args.size == 0 ? "EN" : args[0]
```

上記では1文にまとめていましたがブロックで書くこともできます。ifを文ではなく式として使う場合はelseが必須となります。

```kotlin
val language = if (args.size == 0) {
    "EN"
} else {
    args[0]
}
```

もちろん他の言語でよく見るような書き方もできます。

```kotlin
var language = ""
if (args.size == 0) {
    language = "EN"
} else {
    args[0]
}
```

その他注意点としては、ifの条件文にあたる部分は()で囲う必要があるということです。

### when式

whenはSwiftで言うとswitchのようなものです。条件を満たすものが見つかるまで順番に比較を行っていきます。

複数条件に当てはまる場合でも、最初に当てはまったところの処理だけが実行されるようです。

```kotlin
val x = 1
when (x) {
    in 1..10 -> println("1 <= x <= 10")
    in 0..5 -> println("0 <= x <= 5")
    else -> println("other")
}
// 出力 : 1 <= x <= 10
```

条件分岐は「,」でまとめることもできます。

```kotlin
val x = 1
when (x) {
    0,1 -> println("x = 0 or 1")
    else -> println("x != 0 or 1")
}
```

ちなみにwhenは式としても文としても使うことができます。
他にもwhenにはいろいろな使い方があるのですが、このチュートリアルの例からどんどん外れていきそうなので、またwhenが出てきた時に他の使い方について書きます。whenについては[こちら](http://kotlinlang.org/docs/reference/control-flow.html#when-expression)に詳しく書かれています。

## An object-oriented Hello

ここで初めてクラスが登場しました。

```kotlin
class AnObjectOrientedHello(val name: String) {
    fun greet() {
        println("Hello, ${name}");
    }
}

fun main(args: Array<String>) {
    AnObjectOrientedHello(args[0]).greet()
}
```

クラス宣言の中でプライマリコンストラクタが指定できるようになっています。このように書くこともできるのですが、プライマリコンストラクタがアノテーションや可視性修飾子を持っていない場合は`constructor`を省略して書くことができます。

```kotlin
class AnObjectOrientedHello constructor(val name: String) {
}
```

クラスもまだまだ奥深いのですが話が逸れそうなのでこのへんまでにしておきます。

# 感想

## シンタックスエラー、警告がわかりにくい

全体をダークカラーにしているからかもしれませんが、エラーが起こっている箇所がわかりにくいです。
![スクリーンショット 2017-04-14 13.56.03.png](https://qiita-image-store.s3.amazonaws.com/0/100736/ed796e2a-b9ba-4572-3993-0334f4517200.png)
ファイル名と該当箇所に赤い波線がついているのですがいまいち見えづらい。警告に関しても波線はついているものの、カーソルを当てないと豆電球マークが出てきてくれなくて目立たない。
![スクリーンショット 2017-04-14 14.31.54.png](https://qiita-image-store.s3.amazonaws.com/0/100736/bfd1989c-898c-19b9-72b5-bbb4df30425f.png)
Xcodeの場合は左にはっきりとマークが出るのでわかりやすいなと思いました。
![スクリーンショット 2017-04-14 14.45.44.png](https://qiita-image-store.s3.amazonaws.com/0/100736/5e961879-b481-5dfd-ac9b-bb7f569bec36.png)
↓↓↓↓↓黄色三角クリック↓↓↓↓↓
![スクリーンショット 2017-04-14 14.44.06.png](https://qiita-image-store.s3.amazonaws.com/0/100736/7fe6a480-78b9-ed2c-e72f-5fc1f7523b6a.png)

## 柔軟性が高い

柔軟性と表現するのがいいのかわからないのですが、()があってもなくても良かったり、ブロック使っても1行で書いても良かったりと、かなり自由だなと思いました。ただその分人によって書き方が違ってきて、チーム開発でいろんな書き方が混じりそうだなと思ったりもしました。その点Swiftも同じですが。