Kotlin文法 - アノテーション、リフレクション、型安全なビルダー、動的型


# はじめに

[Kotlin文法 - this、等価性、演算子オーバーロード、Null安全、例外](http://qiita.com/k5n/items/6fe586bf2e5530684681)の続き。

[Kotlin Reference](https://kotlinlang.org/dscs/reference/)のOther章Annotations, Reflection, Type-Safe Builders, Dynamic Typeの大雑把日本語訳。適宜説明を変えたり端折ったり補足したりしている。

# アノテーション

## アノテーション宣言

アノテーションはコードにメタデータを付加する手段。アノテーションを宣言するには、*class* の前に *annotation* 修飾子を付ける。

```kotlin
// Fancyアノテーションを宣言する
annotation class Fancy
```

アノテーションクラスをメタアノテーションで修飾することで、アノテーションの付加属性を指定できる。

 - [@Target](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.annotation/-target/index.html) はアノテーションを付けられる要素のあり得る種類（クラス、関数、プロパティ、式など）を指定する。
 - [@Retention](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.annotation/-retention/index.html) は、アノテーションをコンパイルされたクラスファイルに含めるかと、実行時にリフレクションを通して可視化するかどうかを指定する。デフォルトはどちらも *true*。
 - [@Repetable](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.annotation/-repeatable/index.html)は１つのエレメントに同じアノテーションを複数回使うことを許可する。
 - [@MustBeDocumented ](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.annotation/-must-be-documented/index.html)はアノテーションを公開APIの一部とするか、生成されるAPIドキュメントに表示されるクラスやメソッドのシグネチャに含めるべきかどうかを指定する。

```kotlin
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION,
        AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION)
@Retention(AnnotationRetention.SOURCE)
@MustBeDocumented
public annotation class Fancy
```

### 使い方

```kotlin
@Fancy class Foo {
  @Fancy fun baz(@Fancy foo: Int): Int {
    return (@Fancy 1)
  }
}
```

もしクラスのプライマリコンストラクタを修飾したいなら、コンストラクタ宣言で *constructor* を付ける必要がある。アノテーションはその前に付ける。

```kotlin
class Foo @Inject constructor(dependency: MyDependency) {
  // ...
}
```

アクセサにも付けられる。

```kotlin
class Foo {
    var x: MyDependency? = null
        @Inject set
}
```

### コンストラクタ

アノテーションはパラメータを取るコンストラクタを持つかもしれない。

```kotlin
annotation class Special(val why: String)

@Special("example") class Foo {}
```

パラメータの型として許されるのは以下。

 - Javaのプリミティブ型に対応する型(Int, Longなど）
 - 文字列
 - クラス(Foo::class)
 - enum
 - 他のアノテーション
 - 上に挙げた型の配列

アノテーションを他のアノテーションのパラメータとして使う場合、その名前の前に @ は付けない。

```kotlin
public annotation class ReplaceWith(val expression: String)

public annotation class Deprecated(
        val message: String,
        val replaceWith: ReplaceWith = ReplaceWith(""))

@Deprecated("This function is deprecated, use === instead", ReplaceWith("this === other"))
```

### ラムダ

アノテーションはラムダにも使うことができる。ラムダのボディが生成される先の *invoke()* メソッドに適用される。これは[Quasar](http://www.paralleluniverse.co/quasar/)（並列性の制御にアノテーションを使う）のようなフレームワークで便利。

```kotlin
annotation class Suspendable

val f = @Suspendable { Fiber.sleep(10) }
```

## アノテーション利用場所ターゲット

プロパティやプライマリコンストラクタのパラメータを修飾するとき、Kotlinの要素に対応するJava要素が複数生成され、それゆえ生成されるJavaバイトコードにアノテーションが配置される場所が複数生じてしまう。アノテーションの生成を正確に指定するため、以下の書式が使える。

```kotlin
// コンストラクタの引数にvalを付けるとプロパティも一緒に生成される。
// プロパティにはバッキングフィールドとゲッターが生成される。
// アノテーションは引数に付くの？プロパティのフィールド？それともゲッター？
class Example(@field:Ann val foo,    // Javaフィールドを修飾する
              @get:Ann val bar,      // Javaのgetterを修飾する
              @param:Ann val quux)   // Javaコンストラクタ引数を修飾する
```

同じ書式はファイル全体の修飾にも使える。それにはファイルのトップレベルで、*package* 命令の前か、デフォルトパッケージなら全ての *import* の前に、*file* ターゲット付きのアノテーションを置く。

```kotlin
@file:JvmName("Foo")

package org.jetbrains.demo
```

同じターゲットに複数のアノテーションが必要なら、括弧を使って中にアノテーションを並べることで、ターゲットを繰り返し書くのを避けられる。

```kotlin
class Example {
     // @set:Inject @set:VisibleForTesting と書かなくても以下のように書ける
     @set:[Inject VisibleForTesting]
     public var collaborator: Collaborator
}
```

利用場所ターゲットの全てのリストは以下。

 - file
 - property （このターゲット付きのアノテーションはJavaからは見えない）
 - field
 - get（プロパティのゲッター）
 - set（プロパティのセッター）
 - receiver（拡張関数やプロパティのレシーバパラメータ）
 - param（コンストラクタ引数）
 - setparam（プロパティのセッター引数）

拡張関数のレシーバパラメータを修飾するには以下の書式を使う。

```kotlin
fun @receiver:Fancy String.myExtension() { }
```

利用場所ターゲットを指定しない場合、利用されているアノテーションの *@Target* に従って選択される。もし複数のターゲットがあり得るなら、次のリストから最初の適用可能なターゲットが使われる。

 - param
 - property
 - field

## Javaアノテーション

JavaアノテーションはKotlinと100%互換性がある。

```kotlin
import org.junit.Test
import org.junit.Assert.*

class Tests {
  @Test fun simple() {
    assertEquals(42, getTheAnswer())
  }
}
```

Javaで書かれたアノテーションのパラメータは順番が定義されていないので、引数を渡すのに通常の関数呼び出しの書式は利用できない。代わりに名前付き引数を使う必要がある。

```java
// Java
public @interface Ann {
    int intValue();
    String stringValue();
}
```

```kotlin
// Kotlin
@Ann(intValue = 1, stringValue = "abc") class C
```

Javaと同様に *value* パラメータは特別で、名前を明示しなくていい。

```java
// Java
public @interface AnnWithValue {
    String value();
}
```

```kotlin
// Kotlin
@AnnWithValue("abc") class C
```

もしJavaの *value* パラメータが配列なら、Kotlinでは *vararg* （可変長）パラメータになる。

```java
// Java
public @interface AnnWithArrayValue {
    String[] value();
}
```

```kotlin
// Kotlin
@AnnWithArrayValue("abc", "foo", "bar") class C
```

もしアノテーションの引数としてクラスを指定する必要があるなら、Kotlinクラス(KClass)を使う。Kotlinコンパイラは自動的にそれをJavaクラスに変換するので、Javaコードは普通にアノテーションと引数を見ることができる。

```kotlin
import kotlin.reflect.KClass

annotation class Ann(val arg1: KClass<*>, val arg2: KClass<out Any?>)

@Ann(String::class, Int::class) class MyClass
```

アノテーションインスタンスの値はKotlinコードにはプロパティに見える。

```java
// Java
public @interface Ann {
    int value();
}
```

```kotlin
// Kotlin
fun foo(ann: Ann) {
    val i = ann.value
}
```

# リフレクション

リフレクションは実行時にプログラムの構造を覗き見ることを可能とする言語やライブラリの仕組みである。Kotlinは関数やプロパティを第1級市民にしており、それらを覗き見る（つまり実行時に関数やプロパティの型や名前が分かる）ことは関数型やリアクティブスタイルを簡単に用いることと密接に結びついている。

注：Javaプラットフォームでは、リフレクション機能を使うランタイムコンポーネントは別のJARファイル(kotlin-reflect.jar)として配布される。これによってリフレクションを使わないアプリケーションに要求されるランタイムライブラリサイズを削減している。もしリフレクションを使うなら、プロジェクトのクラスパスにその .jar ファイルを追加するのを忘れないこと。

## クラス参照

最も基本的なリフレクション機能は、Kotlinクラスへの実行時参照を取得すること。静的に分かっているKotlinクラスへの参照を取得するには、クラスリテラル書式が利用できる。

```kotlin
val c = MyClass::class
```

参照はKClass型の値。

Kotlinクラス参照はJavaクラス参照と同じではないことに注意。Javaクラス参照を得るには、*KClass* インスタンスの *.java* プロパティを使う。

## 関数参照

以下のような名前付き関数があるとき、

```kotlin
fun isOdd(x: Int) = x % 2 != 0
```

これを簡単に直接呼び出せる( *isOdd(5)* )。けどこれを値として渡すこともできる。つまり他の関数に。それには *::* 演算子を使う。

```kotlin
val numbers = listOf(1, 2, 3)
println(numbers.filter(::isOdd)) // [1, 3]を表示する
```

ここで *::isOdd* は *(Int) -> Boolean* 関数型の値である。

*::* 演算子はオーバーロード関数には使えないことに注意。将来的には、関数の特定のオーバーロードが選択可能なようにパラメータ型を指定する書式を提供することを計画している。

## 例：関数合成

次の関数を考えてみる。

```kotlin
fun <A, B, C> compose(f: (B) -> C, g: (A) -> B): (A) -> C {
    return { x -> f(g(x)) }
}
```

これは渡された２つの関数を合成したものを返す。つまり compose(f, g) = f(g(*)) 。これを呼び出し可能な参照に適用できる。

```kotlin
fun length(s: String) = s.size

// isOdd(length(s)) の動作をする関数を作って oddLength に格納する
val oddLength = compose(::isOdd, ::length)
val strings = listOf("a", "ab", "abc")

// 渡した文字列のリストのうち、長さが奇数のものだけ表示する
println(strings.filter(oddLength)) // "[a, abc]"と表示される
```

## プロパティ参照

Kotlinで第1級オブジェクトとしてプロパティにアクセスするのにも、*::* 演算子が利用できる。

```kotlin
var x = 1

fun main(args: Array<String>) {
    println(::x.get()) // "1"が表示される
    ::x.set(2)
    println(x)         // "2"が表示される
}
```

*::x* は *KProperty&lt;Int&gt;* 型のプロパティオブジェクトと等価である[^1]。これを使うと *get()* で値を読みだしたり、*name* プロパティでプロパティ名を取得したりできる。詳細は[KPropertyクラスのドキュメント](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.reflect/-k-property/index.html)を参照。

[^1]: 上の例でxはvarなのでKMutableProperty<Int>になるはず。KProperty<Int>になるのはvalのとき。

変更可能なプロパティ(例えば *var y = 1*)には、*::y* は *set()* を持つ *KMutableProperty&lt;Int&gt;* を返す。

プロパティ参照は引数のない関数が期待される場所で使うことができる。

```kotlin
val strs = listOf("a", "bc", "def")
// mapの処理として、各String要素のlengthプロパティを指定する
println(strs.map(String::length)) // [1, 2, 3] を表示する
```

クラスメンバのプロパティにアクセスするには修飾する。

```kotlin
class A(val p: Int)

fun main(args: Array<String>) {
    val prop = A::p         // Aクラスのpプロパティ参照をpropに代入
    println(prop.get(A(1))) // "1"を表示する
}
```

拡張プロパティには以下のようにする。

```kotlin
// StringにlastChar拡張プロパティを用意
val String.lastChar: Char
  get() = this[size - 1]

fun main(args: Array<String>) {
  println(String::lastChar.get("abc")) // "c"を表示する
}
```

## Javaリフレクションとの相互運用性

Javaプラットフォームでは、標準ライブラリがリフレクションクラスの拡張を用意している。その拡張がJavaリフレクションオブジェクトとの間のマッピングを提供する。例えば、バッキングフィールドやKotlinプロパティのgetterとして提供されるJavaメソッドを見つけるために、こんな風に書ける。

```kotlin
// 標準ライブラリが提供しているJavaとのリフレクション相互運用拡張を使う
import kotlin.reflect.jvm.*
 
class A(val p: Int)
 
fun main(args: Array<String>) {
    // KotlinクラスであるAのプロパティpのJavaでのGetterメソッドを表示
    println(A::p.javaGetter) // "public final int A.getP()" と表示される
    // KotlinクラスであるAのプロパティpのJavaでのバッキングフィールドを表示
    println(A::p.javaField)  // "private final int A.p" と表示される
}
```

Javaクラスに対応するKotlinクラスを取得するには、*.kotlin* 拡張プロパティを使う。

```kotlin
fun getKClass(o: Any): KClass<Any> = o.javaClass.kotlin
```

## コンストラクタ参照

コンストラクタもメソッドやプロパティと同じように参照できる。コンストラクタと引数が同じで適切な型の戻り値を持つ関数型オブジェクトが期待される場所なら、どこでも利用できる。コンストラクタは *::* 演算子の後にクラス名を加えることで参照できる。「引数なしで *Foo* を返す関数」を引数として期待する、次の関数を考えてみよう。

```kotlin
class Foo

fun function(factory : () -> Foo) {
    val x : Foo = factory()
}
```

*::Foo* を使うことで、*Foo* の引数なしコンストラクタを、こんな風に簡単に呼び出せる。

```kotlin
function(::Foo)
```

# 型安全なビルダー

[ビルダー](http://www.groovy-lang.org/dsls.html#_nodebuilder)の概念はGroovyコミュニティではかなりポピュラー。ビルダーを用いると準宣言的にデータを定義できる。ビルダーは[XML生成](http://www.groovy-lang.org/processing-xml.html#_creating_xml)、[UIコンポーネントのレイアウト](http://www.groovy-lang.org/swing.html)、[3Dシーンの描写](http://www.artima.com/weblogs/viewpost.jsp?thread=296081)などで便利。

多くの利用ケースで、Kotlinは型安全なビルダーを提供できる。型安全性であることでGroovyでの動的型付け実装よりも魅力的なものになる。

残りの事例では、Kotlinは動的片付けビルダーをサポートする。

## 型安全なビルダーの例

次のコードを考えてみよう。

```kotlin
import com.example.html.*

fun result(args: Array<String>) =
  html {
    head {
      title {+"KotlinでのXMLエンコーディング"}
    }
    body {
      h1 {+"KotlinでのXMLエンコーディング"}
      p  {+"このフォーマットはXMLマークアップの代替として利用できる。"}

      // 属性とテキストを持つ要素
      a(href = "http://kotlinlang.org") {+"Kotlin"}

      // 複合コンテンツ
      p {
        +"これは幾つかの"
        b {+"複合された"}
        +"テキスト。詳細は"
        a(href = "http://kotlinlang.org") {+"Kotlin"}
        +"プロジェクトを参照。"
      }
      p {+"いくらかのテキスト"}

      // 生成される内容
      p {
        for (arg in args)
          +arg
      }
    }
  }
```

これは完全に正当なKotlinコードである。[ここ](http://try.kotlinlang.org/#/Examples/Longer%20examples/HTML%20Builder/HTML%20Builder.kt)で（変更してブラウザで実行して）このコードをオンラインで試すことができる。

## どうやって動作しているか

Kotlinでの型安全なビルダーの実装メカニズムを順に見ていこう。まず最初に組み立てたいモデルを定義する。ここの例ではHTMLタグのモデルが必要だ。これは一連のクラスを用意すれば済む。例えば *&lt;html&gt;* タグを表すのは *HTML* クラスで、これは *&lt;head&gt;* や *&lt;body&gt;* を子供として定義する。（宣言は下を参照。）

コードの中でこんな風に書けるのは何故なのか思い出してみよう。

```kotlin
html {
 // ...
}
```

*html* は実際にはラムダ式を引数に取る関数だ。この関数は次のように定義されている。

```kotlin
fun html(init: HTML.() -> Unit): HTML {
  val html = HTML()
  html.init()
  return html
}
```

この関数は*init* という名前の１つの引数を取り、その引数自身が関数である。（引数の）関数の型は *HTML.() -&gt; Unit* で、これはレシーバ付きの関数だ。これは関数に *HTML* 型のインスタンス（レシーバ）を渡さなければならず、関数の中でそのインスタンスのメンバを呼び出せることを意味する。レシーバは *this* キーワードを通してアクセスできる。

```kotlin
html {
  this.head { /* ... */ }
  this.body { /* ... */ }
}
```

（*head* と *body* は *html* のメンバ関数。）

ここで *this* は普通は省略できる。もうすでにすごくビルダーっぽい感じに見える。

```kotlin
html {
  head { /* ... */ }
  body { /* ... */ }
}
```

それで、この呼び出しは何をやってるんだろう？上で定義した *html* 関数のボディを見てくれ。新しい *HTML* インスタンスを生成してる。それから引数として渡された関数を呼び出して初期化する（この例では *HTML* インスタンスの *head* と *body* を呼び出しを行ってる）。それからそのインスタンスを返す。これこそビルダーがやるべきことだ。

*HTML* クラスの *head* と *body* 関数は *html* に似た感じで定義されている。唯一の違いは構築したインスタンスを *HTML* インスタンスの *children* に追加することだけ。

```kotlin
fun head(init: Head.() -> Unit) : Head {
  val head = Head()
  head.init()
  children.add(head)  // 内部のコレクションに追加する
  return head
}

fun body(init: Body.() -> Unit) : Body {
  val body = Body()
  body.init()
  children.add(body)  // 内部のコレクションに追加する
  return body
```

実際これら２つの関数は同じことをやっているので、ジェネリックバージョン *initTag* を用意できる。

```kotlin
  protected fun <T : Element> initTag(tag: T, init: T.() -> Unit): T {
    tag.init()
    children.add(tag)
    return tag
  }
```

するとさっきの関数はすっきりとこうなる。

```kotlin
fun head(init: Head.() -> Unit) = initTag(Head(), init)

fun body(init: Body.() -> Unit) = initTag(Body(), init)
```

これで *head* と *body* タグを構築するのにこれらが使えるようになった。

もう一個ここで考察するのは、どうやってテキストをタグの中に入れるかだ。上の例でこんな感じで書いた。

```kotlin
html {
  head {
    title {+"XML encoding with Kotlin"}
  }
  // ...
}
```

基本的にはタグの中に文字列を書くだけなのだが、その前に *+* がある。これは *unaryPlus()* 演算子関数を呼び出す。この演算子は（*Title* の親の）*TagWithText* 抽象クラスのメンバである拡張関数 *unaryPlus* によって定義されている。

```kotlin
// title内で + をStringに対して呼び出すと、StringのunaryPlusメソッドまたは拡張関数を探す。
// するとTitleの親クラスであるこのTagWithTextクラスに、String.unaryPlus拡張関数が見つかるので、
// 文字列をレシーバにしてこれを呼び出す。
abstract class TagWithText(name: String) : Tag(name) {
    operator fun String.unaryPlus() {
        children.add(TextElement(this))  // ここでのthisはレシーバで、型はString
    }
}
```

ここで前置の *+* がやっているのは、文字列を *TextElement* のインスタンスにラップして、それを *children* コレクションに追加している。これで文字列はタグ木構造の正式な一部になれた。

これら全ては上の方にあるビルダーの例のトップで *import* している *com.example.html* パッケージに定義されている。

## com.example.htmlパッケージの定義全部

```kotlin
package com.example.html

interface Element {
    fun render(builder: StringBuilder, indent: String)
}

class TextElement(val text: String) : Element {
    override fun render(builder: StringBuilder, indent: String) {
        builder.append("$indent$text\n")
    }
}

abstract class Tag(val name: String) : Element {
    val children = arrayListOf<Element>()
    val attributes = hashMapOf<String, String>()

    protected fun <T : Element> initTag(tag: T, init: T.() -> Unit): T {
        tag.init()
        children.add(tag)
        return tag
    }

    override fun render(builder: StringBuilder, indent: String) {
        builder.append("$indent<$name${renderAttributes()}>\n")
        for (c in children) {
            c.render(builder, indent + "  ")
        }
        builder.append("$indent</$name>\n")
    }

    private fun renderAttributes(): String? {
        val builder = StringBuilder()
        for (a in attributes.keys) {
            builder.append(" $a=\"${attributes[a]}\"")
        }
        return builder.toString()
    }


    override fun toString(): String {
        val builder = StringBuilder()
        render(builder, "")
        return builder.toString()
    }
}

abstract class TagWithText(name: String) : Tag(name) {
    operator fun String.unaryPlus() {
        children.add(TextElement(this))
    }
}

class HTML() : TagWithText("html") {
    fun head(init: Head.() -> Unit) = initTag(Head(), init)

    fun body(init: Body.() -> Unit) = initTag(Body(), init)
}

class Head() : TagWithText("head") {
    fun title(init: Title.() -> Unit) = initTag(Title(), init)
}

class Title() : TagWithText("title")

abstract class BodyTag(name: String) : TagWithText(name) {
    fun b(init: B.() -> Unit) = initTag(B(), init)
    fun p(init: P.() -> Unit) = initTag(P(), init)
    fun h1(init: H1.() -> Unit) = initTag(H1(), init)
    fun a(href: String, init: A.() -> Unit) {
        val a = initTag(A(), init)
        a.href = href
    }
}

class Body() : BodyTag("body")
class B() : BodyTag("b")
class P() : BodyTag("p")
class H1() : BodyTag("h1")

class A() : BodyTag("a") {
    public var href: String
        get() = attributes["href"]!!
        set(value) {
            attributes["href"] = value
        }
}

fun html(init: HTML.() -> Unit): HTML {
    val html = HTML()
    html.init()
    return html
}
```

# 動的型

注：JVMをターゲットにしたコードでは動的型はサポートされない。

Kotlinは静的型付け言語でありながら、Javascriptエコシステムのような型のないまたは型付けのゆるい環境とも相互運用しないといけない。これらの利用状況を手助けするために、言語内で動的な型が利用できる。

```kotlin
val dyn: dynamic = ...
```

動的型は基本的にKotlinの型チェックを止める。

 - この型の値はどんな変数にも入れられ、パラメータとしてどこにでも渡せる。
 - どんな値も *dynamic* 型の変数に代入でき、パラメータとして *dynamic* を取る関数に渡せる。
 - これらの値でnullチェックは無効


*dynamic* 型の最も特徴的な機能は *dynamic* 変数に対してどんなプロパティや関数も呼び出せること。

```kotlin
dyn.whatever(1, "foo", dyn) // 'whatever' はどこにも定義されていない
dyn.whatever(*array(1, 2, 3))
```

Javascriptプラットフォームでは、このコードは「そのまま」コンパイルされる。つまり Kotlinでの *dyn.whatever(1)* は生成されたJavascriptコードでは *dyn.whatever(1)* となる。

動的呼び出しは常に結果として *dynamic* を返す。なので自由にチェイン呼び出しできる。

```kotlin
dyn.foo().bar.baz()
```

動的呼び出しにラムダを渡す時は、デフォルトで全てのパラメータの型は *dynamic* になる。

```kotlin
dyn.foo {
  x -> x.bar() // x は dynamic
}
```

# 次へ

これでKotlin文法はおしまい。お疲れ様!!

次は[Kotlin - Javaとの相互運用](http://qiita.com/k5n/items/ceb1f921b27d62fc9fcb)をどうぞ。