12
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Kotlinで関数に渡された型パラメータによって処理を分岐させる方法

Last updated at Posted at 2016-02-05

##Injektの不思議な代入
InjektというKotlinのDependency Inejectionフレームワークがある。
これを使って予め登録したオブジェクトを取り出す場合、下記のような記述ができる。

val obj:MyClass = Injekt.get()

一見して、Injekt.get()は返すべきオブジェクトを決定するためになんの情報も受け取っていないように見える。
実は、Injekt.get()は代入先の型にあわせて返すべきオブジェクトを決定している。

##Injekt.get()が返すオブジェクトを決定する仕組み
Injekt.get()はKotlinのreified type parameterという機能と型推論を使うことで返すオブジェクトを決定している。
reified type parameterは実際の型名のように扱える型パラメータだ。
例えば、通常の型パラメータではできないが、is演算子の右辺に置くことやclassオブジェクトを参照することができる。
Injekt.get()には型パラメータが渡されていないように見えるが、Kotlinはその強力な型推論によって代入先の型から推論してうまく型パラメータを渡してくれる。

なお、reified type parameterはinline関数でしか使えないという制約がある。

##実際に、代入先の変数型に合わせた結果を返すサンプル

data class MyClass(
        val id:Int,
        val name:String
)

inline fun <reified T> f1():T {
    val c = T::class
    when (c.qualifiedName) {
        "kotlin.Int" -> return 10 as T
        "kotlin.String" -> return "Hoge" as T
    }
    return "else" as T
}

fun main(args: Array<String>) {
    val c = MyClass(
            id = f1(),
            name = f1()
    )
    println(c)
}

この例ではMyClassのコンストラクタのパラメータ型がf1()のreified type parameterとして渡る。
f1()は与えられた型情報から返すべきオブジェクトを決定する。

##まとめ
reified type parameterを使うことで、クラスオブジェクトを引数に渡さずとも型に応じた柔軟な処理の分岐が可能になる。
この機能は頻繁に使うようなものではないかもしれないが、これを活用することで、より便利なインタフェースを提供することが
できるため、ライブラリやフレームワークの作成者などは知っておくと便利かもしれない。

12
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?