Realm4.3.0でのKotlinサポート追加

※ これは[Android その2 Advent Calendar]( [Android その2 Advent Calendar 2017 - Qiita](https://qiita.com/advent-calendar/2017/android_second) )の10日目の記事です。

---
2017/12/05にRealm 4.3.0が発表されました！ :tada:
このアップデートでRealm + Kotlinが強化されたので紹介です！
# Overview
* `T::class.java`なんてもう書かないで良いよ！
* `RealmModel`のメソッド呼び出しが美しく書けるよ！
* Kotlinで`in`は予約語だよね`oneOf`使って良いよ！

#  `T::class.java`なんてもう書かないで良いよ！
## いままでは
Kotlinを使っている場合、Realmでクエリを記述は以下のようになります。（公式引用）

```Sample.kt
// Instead of this…
val dog = realm.createObject(Dog::class.java)  // create a Dog
realm.delete(Dog::class.java) // Delete All Dogs
realm.where(Dog::class.java)
     .findAllAsync()
     .asFlowable() // Fetch all dogs asynchronously as an RxFlowable
```

これらの引数にはJavaのClassインスタンスを渡す必要があるためです。
ちょっと気持ち悪いですよね。

## これからは
`reified type paramter`を用いた拡張関数の定義により

```Sample.kt
// You do this
val dog = realm.createObject<Dog>()  // create a Dog
realm.delete<Dog>() // Delete All Dogs
realm.where<Dog>()
     .findAllAsync()
     .asFlowable() // Fetch all dogs asynchronously as an RxFlowable
```
のように記述できます！（公式引用）

これに尽きちゃうのですが、簡単に実装を見てみましょう。

## Extensionの実装
恩恵をうけるのは以下のメソッドになります。
* where
* delete
* createObject

ここでは`where`を見てみることにします。

```RealmExtensions.kt
inline fun <reified T : RealmModel> Realm.where(): RealmQuery<T> {
    return this.where(T::class.java)
}
```

見て取れる通り、`reified`を使ってJavaのClassインスタンスを取得することで実現しているようです。
[Reified Type Parameters](https://kotlinlang.org/docs/reference/inline-functions.html#reified-type-parameters)は関数の中で`T`を実際の型として扱える機能ですね。便利だ…

# `RealmModel`のメソッド呼び出しが美しく書けるよ！
## 補足
Realmでは、`RealmObject`クラスを継承することでモデルを定義します。

```ExampleModel.kt
open class Example(
        open var name: String = "",
        open var status: Int = 0,
) : RealmObject() {}
```

アプリによっては、別のベースモデルクラスを継承させたいという場面はよくあるとおもいますが、
この場合、`RealmObject`を継承する以外の選択肢として`RealmModel`インタフェースと`@RealmClass`アノテーションを用いる方法があります。

これを用いると

```ExampleModel.kt
@RealmClass
open class Example(
        open var name: String = "",
        open var status: Int = 0,
) : RealmModel {}
```
のようになります。

## いままでは
`RealmObject`がインスタンスメソッドとして提供していたメソッドは、提供されているstaticメソッドを利用する必要がありました。

```Sample.kt
// RealmObjectを継承する場合
example.isValid()
example.addChangeListener(listener)

// RealmModelを実装する場合
RealmObject.isValid(example)
RealmObject.addChangeListener(example, listener)
```

## これからは
拡張メソッドとして提供され、`RealmModel`を実装させた場合でも

```Example.kt
@RealmClass
open class Example(
        open var name: String = "",
) : RealmModel {}

example.isValid()
example.addChangeListener(listener)
```
のように記述することができます！美しい！！

こちらも簡単に実装を見てみましょう。

## Extension実装
恩恵をうけるのは以下のメソッドになります。
* deleteFromRealm
* isValid
* isManaged
* isLoaded
* load
* E.addChangeListener
* E.removeChangeListener
* removeAllChangeListeners

ここでは`deleteFromRealm `を見てみることにします。

```RealmModelExtensions.kt
fun RealmModel.deleteFromRealm() {
    RealmObject.deleteFromRealm(this)
}
```

簡単なExtensionですが、圧倒的に美しくなりますね。感謝。

# Kotlinで`in`は予約語だよね`oneOf`使って良いよ！
## いままでは
Kotlinでは`in`が予約語のため、クエリで使用する場合以下のように書く必要があります。（公式引用）

```Sample.kt
val dogs = realm
     .where<Dog>()
     .`in`("name", arrayOf("Larry", "Curly", "Moe"))
```

## これからは
`oneOf`という拡張メソッドにより以下のように記述できます。（公式引用）

```Sample.kt
val dogs = realm
     .where<Dog>()
     .oneOf("age", arrayOf("Larry", "Curly", "Moe"))
```

### ※ 注釈
[Realmの公式ブログ](https://realm.io/blog/realm-4-3-0-released-w-first-class-support-for-kotlin/#new-keyword)では`anyOf`を追加したよ！と記載されていますが、誤植？でしょうか。。
`anyOf`は実装されていないので`oneOf`を使いましょう！

## Extension実装
`String`の比較を行う場合の実装を見てみます。

```RealmQueryExtensions.kt
fun <T : RealmModel> RealmQuery<T>.oneOf(propertyName: String,
                                         value: Array<String?>,
                                         casing: Case = Case.SENSITIVE): RealmQuery<T> {
    return this.`in`(propertyName, value, casing)
}
```

ちょっとしたことですが、Kotlinでの実装が気持ちよくなりますね！！

# まとめ
著名なライブラリがKotlinで使いやすいようアップデートするケースを最近良く見ますね！
Kotlinはきもちよく書きたいですよね！素敵！！

# Links
* [Realm + Kotlin just got even better with Realm 4.3.0](https://realm.io/blog/realm-4-3-0-released-w-first-class-support-for-kotlin/)
*  [realm-java/realm/kotlin-extensions at master · realm/realm-java](https://github.com/realm/realm-java/tree/master/realm/kotlin-extensions)
* [Kotlin M10で追加されたreified type parameterがいい感じ - 算譜王におれはなる!!!!](http://taro.hatenablog.jp/entry/2015/01/29/223239)