Kotlin 0.12からKotlin 1.0.2にアップグレードした際にやったこと

# Kotlin 0.12からKotlin 1.0.2にアップグレードした際にやったこと

Kotlinが1.0系になり、言語仕様が安定してきたとの事(後述)なので、
技術的な検証として、[過去にKotlin 0.12で作ったアプリ](http://qiita.com/omochimetaru/items/98e015b0b694dd97f323)のKotlin 1.0.2へのアップグレード対応を試してみました。

コンパイラバージョンを切り替えたところ、1800個のコンパイルエラーが生じましたｗ
同じような境遇の方は少ないと思いますが、自分の事例を紹介します。

## 作業時間

上記の修正ですが、合計で3時間ほどの作業でコンパイルできるようになりました。
特に困難なものもありませんでした。

## 言語仕様の安定性について

[公式のKotlin 1.0についての記事](https://blog.jetbrains.com/kotlin/2016/02/kotlin-1-0-released-pragmatic-language-for-jvm-and-android/)によると、

> As of 1.0, we are committed to long-term backward compatibility of the language and its standard library (kotlin-stdlib):

と書いてあります。
0系から1系での追従でも大したことはなかったので、
今後のアップグレード追従についてはだいぶ楽観視できます。

# import asでパッケージに別名を付けることができなくなった

jp.co.aaa.hogeネームスペースにHogeクラスが定義されている場合、
以前は下記のように書くことができました。

```kotlin
import jp.co.aaa.hoge as hoge

val x = hoge.Hoge()
```

しかし、このようにパッケージレベルで別名を付けることができなくなってしまいました。
上記のケースでは、Hoge自体に別名をつける必要があります。

```kotlin
import jp.co.aaa.hoge.Hoge as HogeHoge

val x = HogeHoge()
```

前者の方法であれば、jp.co.aaa.hogeの中にどのようなクラス名が入っていても、
別名のhogeさえ衝突しないのであれば、`hoge.XXX`表記を使う限り衝突の心配が無かったのですが、
できなくなってしまい残念です。

# Javaのクラスのメソッド名がKotlin風に変更された

java.util.Listで要素数を取得する`size()`メソッドは、
以前は`list.size()`のように呼ぶことができました。

今のKotlinではこれは`size`プロパティに変更されています。
呼び出し部分の丸括弧があるとコンパイルエラーになります。

このようにJavaのクラスのメソッド名が、
Kotlin風のメソッド名やプロパティに変更されました。
多くの変更がされているようですが、
僕が踏んだものを掲載します。

`array.length()`->`array.length`
`list.size()`->`list.size`
`list.reverse()`->`list.reversed()`
`list.remove()`->`list.removeAt()`
`map.values()`->`map.values`
`map.keySet()`->`map.keys`
`map.entrySet()`->`map.entries`
`entry.getKey()`->`entry.key`
`entry.getValue()`->`entry.value`

あちこちで踏んでいたので修正には手間がかかりましたが、
修正後の仕様は綺麗なものばかりで、個人的には嬉しい修正です。

# Mapの要素アクセスがnullableを返すようになった

上記のjavaライブラリの変更とも関係して、
`Map<T>`の要素アクセス`map[key]`で以前は`T!`を返していたものが、
`T?`を返すようになりました。
`T!`で来ている部分を`T`で扱っていたケースでコンパイルエラーになります。

既存コードは既にテストされているものだったので、
マイグレーションとしては`!!`を付けるだけの修正でした。

# プロパティのバッキングフィールド名が変更された

以前はプロパティ名`prop`に対して、`$prop`というドル記号プレフィックスをつけたものが、
バッキングフィールドとして暗黙定義されていましたが、
`field`という固定のキーワードに変更されました。

# オペレータオーバーロードにoperatorキーワードが必要になった

以前は`fun plus()`のようなメソッドを定義すれば、
それだけで`+`演算子の実装を与えることができました。
それが、`operator fun plus()`のように、
`operator`キーワードの指定が必要になりました。

# 単項演算子の関数名が変更された

以前は単項演算子の`+`と`-`は`plus`と`minus`でした。
これが`unaryPlus`と`unaryMinus`に変わりました。
二項演算子は`plus`のままです。

# アノテーションに`@`がついて、命名が変わった

`suppress("UNUSED_PARAMETER")`などと書いていたところが、
`@Suppress("UNUSED_PARAMETER")`と書くように変わりました。
`@`がついてアッパーキャメルケースになり、Javaの仕様に近づきました。

# 変数名`_`が予約された

クロージャ引数を読み捨てるようなケースで、
それをあらわすルールとして`_`という変数名を使ったりしていましたが、
これがコンパイルエラーになりました。

Swiftで明示的に読み捨てる場合、`let _ = ...`と、
`_`を使うのでそれに似せて使っていたのですができなくなってしまいました。

# ジェネリック関数の型パラメータ指定位置が変わった

ジェネリック関数の型パラメータの指定位置が変わりました。
以前は下記のように関数名とパーレンの間に書きました。

```
fun hoge<T>(arg: T)
```

現在は下記のように`fun`と関数名の間に書きます。

```
fun <T> hoge(arg: T)
```

前者の仕様だとswiftと同じ位置なのでわかりやすかったのですが、
変わってしまいました。

# Javaクラスオブジェクトの取り出し方が変わった

以前の`java.lang.class<T>`の取り出しは`javaClass<T>()`でした。
これが`T::class.java`に変わりました。

AndroidのIntent呼び出し箇所で使うため、
かなり多くの修正箇所がありました。

新しい仕様のほうが、
`T::class`がKotlinでのクラスオブジェクトで、
それの`java`プロパティとしてJavaでのクラスオブジェクトが取り出せる形なので、
とてもわかりやすくなっていて良いと思います。

# Deprecation警告の抑制アノテーションが変わった

以前は`suppress("DEPRECATED_SYMBOL_WITH_MESSAGE")`だったのですが、
`@Suppress("DEPRECATION")`と変わりました。

わかりやすい名前になって良かったです。