Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Double Context Extension (Kotlin) #Retty_tech_cafe

Double Context Extension (Kotlin) #Retty_tech_cafe

Taro Nagasawa

December 09, 2016
Tweet

More Decks by Taro Nagasawa

Other Decks in Programming

Transcript

  1. 自己紹介 • 長澤 太郎 たろーって呼んでね ◦ @ngsw_taro • エンジニア@エムスリー株式会社 ◦

    Android, Kotlin, Java, Spring, Railsなど • Kotlinエバンジェリスト • ディズニーが好き
  2. Kotlinいいよね! • 型推論 • ラムダ式 • NULL安全 • Extension •

    委譲プロパティ • 分解宣言 • コルーチン • 型エイリアス
  3. Kotlinいいよね! • 型推論 • ラムダ式 • NULL安全 • Extension •

    委譲プロパティ • 分解宣言 • コルーチン • 型エイリアス
  4. Extension(拡張) • 拡張関数 • 拡張プロパティ fun String.hello() { println("Hello, $this")

    } "world".hello() val String.initial: Char? get()=firstOrNull()?.toUpperCase() "world".initial
  5. こんな関数呼び出しをしたい! class MyActivity: FragmentActivity { ... fun showMessage() { //

    myDialog.show(supportFragmentManager, "tag") myDialog.show("tag") } }
  6. こんな関数呼び出しをしたい! class MyActivity: FragmentActivity { ... fun showMessage() { //

    myDialog.show(supportFragmentManager, "tag") myDialog.show("tag") } } DialogFragmentに拡張関数showを生やせば? いや、プロパティsupportFragmentManagerが必要だ...  →FragmentManagerに依存
  7. クラスの中に拡張関数を定義してみる class MyActivity: FragmentActivity { ... fun FragmentDialog.show(tag: String?) {

    show(supportFragmentManager, tag) } fun showMessage() { myDialog.show("tag") } } イケる!?
  8. 再利用ができない問題... class MyActivity: FragmentActivity { ... fun FragmentDialog.show(tag: String?) {

    show(supportFragmentManager, tag) } } class YourActivity: FragmentActivity { ... fun FragmentDialog.show(tag: String?) { show(supportFragmentManager, tag) } }
  9. 再利用ができない問題... class MyActivity: FragmentActivity { ... fun FragmentDialog.show(tag: String?) {

    show(supportFragmentManager, tag) } } class YourActivity: FragmentActivity { ... fun FragmentDialog.show(tag: String?) { show(supportFragmentManager, tag) } } 同じコードが重複する
  10. Double Context Extension • 2つのコンテキストを持った拡張関数 • 命名 by 私 •

    見た目: 型Aの定義中で、型Aに依存しながらも型Bの拡張関 数を生やすことができる class MyActivity: FragmentActivity { ... fun showMessage() { myDialog.show("tag") } }
  11. どう解釈されるか val FragmentActivity.show: DialogFramgnet.(String?)->Unit get() { tag -> show(supportFragmentManager, tag)

    } class MyActivity: FragmentActivity { fun showMessage() { myDialog.show("tag") } ... }
  12. どう解釈されるか val FragmentActivity.show: DialogFramgnet.(String?)->Unit get() { tag -> show(supportFragmentManager, tag)

    } class MyActivity: FragmentActivity { fun showMessage() { myDialog.show("tag") } ... } FragmentActivityの 拡張関数showの呼び出し
  13. どう解釈されるか val FragmentActivity.show: DialogFramgnet.(String?)->Unit get() { tag -> show(supportFragmentManager, tag)

    } class MyActivity: FragmentActivity { fun showMessage() { myDialog.(this.show)("tag") } ... } こう書いても同じ
  14. どう解釈されるか val FragmentActivity.show: DialogFramgnet.(String?)->Unit get() { tag -> show(supportFragmentManager, tag)

    } class MyActivity: FragmentActivity { fun showMessage() { myDialog.show("tag") } ... } 返って来た拡張関数オブジェクトを myDialogをレシーバに、 ”tag”を引数にして呼び出す