Kotlinの@[アットマーク]について

この投稿は、[Kotlin Advent Calendar 2016](http://qiita.com/advent-calendar/2016/kotlin)の22日目の投稿です。

# はじめに

私自身はKotlinを2015年の6月頃から触れ始めたのでKotlin歴は約1年半ぐらいになります
昨年のAdventCalendarはこんな記事を書いてました

* [【Kotlin】 OperatorとInfixでCustom operatorを作る](http://qiita.com/AAkira@github/items/d2cb56eff8952ecfc66b)

2016年1月にリリースされた[FRESH!](https://freshlive.tv)というサービスの開発に携わっています
現在はkaptでも問題なく動作しますが、開発当初はまだKotlinがベータ版のM11だったので
annotation processorを使用するdagger(DI用ライブラリ)の部分以外は全てKotlinで書かれています

今回はannotation processorでも使われるKotlinの`@`の使い方について3つ紹介したいと思います

ちなみに`@`は日本語だと「アットマーク」と呼びますが、英語では「at sign(at symbol)」と呼びます
和製英語と気付かずに使っている人が多いので英語名も覚えておくと良いですよ

## Annotation

```kotlin

annotation class Example(val example: String)

@Example("Hello") class Hoge {
}

```

一番良く見る表現だと思います
説明不要ですね
Javaでもannotationを@で表すので、Kotlinを知らなくても理解出来ると思います


```kotlin
annotation class Example

val hoge = @Example { println("hello world") }
hoge.invoke()
```

annotationもlambdaに書けます
Kotlinならではの書き方という感じですね

`invoke()` を呼ぶとlambdaの中身が呼ばれます

```kotlin
val permission = @NeedsPermission(Manifest.permission.CAMERA) {
    MainActivityPermissionsDispatcher.showCameraWithCheck(this);
}        
view.setOnClickListener { permission.invoke() }
```

現在のプロジェクトではannotation libraryがdaggerしか入っていないので良い使い方が思いつかないのですが、hotchemiさんの[PermissionsDispatcher](https://github.com/hotchemi/PermissionsDispatcher)とかこんな感じで書けると良いのでしょうか？
※ **もちろん妄想なので動きません**
なんか画期的な方法があったら[教えて頂けると嬉しいです！](https://twitter.com/_a_akira)

Kotlinの公式ドキュメントでは[quasar](http://www.paralleluniverse.co/quasar/
)というlibraryの`Suspendable` annotationの例があります

```kotlin
annotation class Suspendable

val f = @Suspendable { Fiber.sleep(10) }
```
threadのライブラリなので、確かに相性は良さそうです

## label

```kotlin
fun func(): Boolean {
      (0..10).forEachIndexed { index, item ->
          println(index)
          return true //①
      }
      return false
}
```

for文の中でreturnをする場合①でreturnをした場合当然ながら
0がprintされて、この関数の戻り値は必ずtrueになります

それでは、indexが5以下の時に5までprintしてtrueを返したい場合はどうでしょうか？
Javaに慣れているとcontinueやbreakが思い浮かぶと思いますが、
これらはfor文等のloop文でのみしか使えないためforEachIndexed内では使えません
ちなみにforEachは`Iterable<T>`の拡張関数になってるので、実体はただの関数です

```kotlin
fun func(): Boolean {
        (0..10).forEachIndexed { index, item ->
            println(index)
            if (index < 5) return@forEachIndexed
            return true
        }
        return false
}
```

returnの後に@をつけて関数のlabelを付けると関数の先頭に戻ります
Javaでいうcontinueに似た動作をします

```Kotlin
Observable.fromCallable { 1 }
          .subscribe {
              if(it == 1) return@subscribe         
              println("not called here")
          }
```

みんな大好きRxのsubscribeも同じように`@subscribe`を付けてreturn出来ます

それでは、lamda式のような無名関数の場合はどうでしょう

```kotlin
val hoge = 5
val lamda = label@ {
    println("printed here")
    if(hoge > 3) return@label
    println("not printed here")
}
lamda.invoke()
```

無名関数の場合は@を使用して自分で名前をつけてあげることで上記と同様の動作になります
Kotlinを使っているとlamda式を使うことが必然的に増えますので、このような書き方を結構します
 
## 内部クラスからの外部クラス参照

最後に内部クラスから外部クラス参照のやり方を見ていきます
上の2つは初心者向けの内容ですが、Kotlinに慣れている方でもこの書き方することが少ない無いので意外に知らない方もいるのではないでしょうか
とは言っても基本的な原理は2番目のlamdaで解説した内容と同じです

Javaでは内部クラスから親クラスのFoo自体を参照する場合以下のような書き方をします

```Java
public class Foo implements View.OnClickListener {

    private Button button;

    public Foo() {

    }

    void hoge() {
        Handler handler = new Handler();
        handler.post(new Runnable(){
            public void run() {
                button.setOnClickListener(Foo.this);
            }});
    }

    @Override
    public void onClick(View view) {

    }
}
```

これをKotlinで書くとこうなります

```kotlin
class Foo : View.OnClickListener {
    private val button: Button? = null

    fun hoge() {
        val handler = Handler()
        handler.post { mButton?.setOnClickListener(this) }
    }

    override fun onClick(view: View) {

    }
}
```

まぁ当然といえば当然でしょう
それではKotlinのrunのような関数内で呼ぶ時はどうなるでしょうか

```kotlin
class Foo : View.OnClickListener {
    private val button: Button? = null

    fun hoge() {
        button?.run {
            setOnClickListener(this) // compile error
            setOnClickListener(this@Foo) // works
        }
    }
}
```

run内のthisはrunを指します
そのため、Fooクラスのclick listenerにbindする場合は`this@{クラス名}`で呼び出せます

これを応用すると、lambda関数内から親クラスのメソッドにアクセスすることも出来ます
例えば、ParentクラスとOtherクラスがあってChildクラス内でOtherクラスの変数を持っていて、
ParentとOtherに同じ名前のメソッドがあります
同じ名前があるとChild内のOtherから`sameNameFunc()`を呼び出すと当然Otherの`sameNameFunc()`が呼ばれます
ちなみに、`{}`を使わずに`=`の書き方をすると`this@Child`無しではコンパイルエラーになります
=> 無限loopになる為
上記を応用して`@Child`でこのクラスのメソッドを指定することで、
親クラスのメソッドを呼び出せます

```kotlin

class Child : Parent() {

    val other = object : Other() {
        override fun sameNameFunc() = this@Child.sameNameFunc() // parent method
    }
}

open class Parent() {
    open fun sameNameFunc() = "Parent"
}

open class Other {
    open fun sameNameFunc() = "Other"
}

```


# おわりに

Kotlin色んな書き方があって面白いですね
明日はdigitaljunkyさんのKotlin + Spring Bootです
お楽しみに