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

KotlinのClass Delegationおさらい #Kotlin_Sansan

KotlinのClass Delegationおさらい #Kotlin_Sansan

Taro Nagasawa

July 01, 2016
Tweet

More Decks by Taro Nagasawa

Other Decks in Programming

Transcript

  1. 自己紹介 • 長澤 太郎 たろーって呼んでね • @ngsw_taro • プログラマー@エムスリー株式会社 ◦

    Android, Kotlin, Java, Scala, Rubyなど • Kotlinエバンジェリスト(JetBrains黙認) ◦ 日本Kotlinユーザグループ代表 • やすべえとディズニーが好き
  2. class CountingHashSet<E> : java.util.HashSet<E>() { var addCount: Int = 0

    private set override fun add(element: E): Boolean { addCount++ return super.add(element) } override fun addAll(elements: Collection<E>): Boolean { addCount += elements.size return super.addAll(elements) } }
  3. class CountingHashSet<E> : java.util.HashSet<E>() { var addCount: Int = 0

    private set override fun add(element: E): Boolean { addCount++ return super.add(element) } override fun addAll(elements: Collection<E>): Boolean { addCount += elements.size return super.addAll(elements) } } クラスの継承
  4. class CountingHashSet<E> : java.util.HashSet<E>() { var addCount: Int = 0

    private set override fun add(element: E): Boolean { addCount++ return super.add(element) } override fun addAll(elements: Collection<E>): Boolean { addCount += elements.size return super.addAll(elements) } } 回数保持のプロパティ
  5. class CountingHashSet<E> : java.util.HashSet<E>() { var addCount: Int = 0

    private set override fun add(element: E): Boolean { addCount++ return super.add(element) } override fun addAll(elements: Collection<E>): Boolean { addCount += elements.size return super.addAll(elements) } } 具象メソッドのオーバライド
  6. class CountingHashSet<E> : java.util.HashSet<E>() { var addCount: Int = 0

    private set override fun add(element: E): Boolean { addCount++ return super.add(element) } override fun addAll(elements: Collection<E>): Boolean { addCount += elements.size return super.addAll(elements) } } カウント +1
  7. class CountingHashSet<E> : java.util.HashSet<E>() { var addCount: Int = 0

    private set override fun add(element: E): Boolean { addCount++ return super.add(element) } override fun addAll(elements: Collection<E>): Boolean { addCount += elements.size return super.addAll(elements) } } 具象メソッドのオーバライド
  8. class CountingHashSet<E> : java.util.HashSet<E>() { var addCount: Int = 0

    private set override fun add(element: E): Boolean { addCount++ return super.add(element) } override fun addAll(elements: Collection<E>): Boolean { addCount += elements.size return super.addAll(elements) } } カウント +要素数
  9. class CountingHashSet<E> : java.util.HashSet<E>() { var addCount: Int = 0

    private set override fun add(element: E): Boolean { addCount++ return super.add(element) } override fun addAll(elements: Collection<E>): Boolean { addCount += elements.size return super.addAll(elements) } } よさそう!わずか15行!
  10. 試してみる val set = CountingHashSet<Int>() set.add(1) set.add(2) println(set.addCount) // 2

    set.addAll(setOf(3, 4, 5)) println(set.addCount) 2回 addを呼び出している
  11. class CountingHashSet<E> : java.util.HashSet<E>() { var addCount: Int = 0

    private set override fun add(element: E): Boolean { addCount++ return super.add(element) } override fun addAll(elements: Collection<E>): Boolean { addCount += elements.size return super.addAll(elements) } } HashSet#addAllは addを呼び出す実装になっている なぜ期待通りに動かなかったのか
  12. class CountingHashSet<E> : java.util.HashSet<E>() { var addCount: Int = 0

    private set override fun add(element: E): Boolean { addCount++ return super.add(element) } override fun addAll(elements: Collection<E>): Boolean { addCount += elements.size return super.addAll(elements) } } ここでカウントして なぜ期待通りに動かなかったのか
  13. class CountingHashSet<E> : java.util.HashSet<E>() { var addCount: Int = 0

    private set override fun add(element: E): Boolean { addCount++ return super.add(element) } override fun addAll(elements: Collection<E>): Boolean { addCount += elements.size return super.addAll(elements) } } HashSetの実装を呼び なぜ期待通りに動かなかったのか
  14. class CountingHashSet<E> : java.util.HashSet<E>() { var addCount: Int = 0

    private set override fun add(element: E): Boolean { addCount++ return super.add(element) } override fun addAll(elements: Collection<E>): Boolean { addCount += elements.size return super.addAll(elements) } } addが呼び出されると、二重でカウント なぜ期待通りに動かなかったのか
  15. class CountingSet<E>(private val set: MutableSet<E>) : MutableSet<E> { var addCount:

    Int = 0 private set override fun add(element: E): Boolean { addCount++ return set.add(element) } override fun addAll(elements: Collection<E>): Boolean { addCount += elements.size return set.addAll(elements) } ...
  16. class CountingSet<E>(private val set: MutableSet<E>) : MutableSet<E> { var addCount:

    Int = 0 private set override fun add(element: E): Boolean { addCount++ return set.add(element) } override fun addAll(elements: Collection<E>): Boolean { addCount += elements.size return set.addAll(elements) } ... インタフェースを実装
  17. class CountingSet<E>(private val set: MutableSet<E>) : MutableSet<E> { var addCount:

    Int = 0 private set override fun add(element: E): Boolean { addCount++ return set.add(element) } override fun addAll(elements: Collection<E>): Boolean { addCount += elements.size return set.addAll(elements) } ... このへんがコンポジション: 実装を継承するのではなく、 実装を保持する。
  18. class CountingSet<E>(private val set: MutableSet<E>) : MutableSet<E> { var addCount:

    Int = 0 private set override fun add(element: E): Boolean { addCount++ return set.add(element) } override fun addAll(elements: Collection<E>): Boolean { addCount += elements.size return set.addAll(elements) } ... さっきと同じ
  19. class CountingSet<E>(private val set: MutableSet<E>) : MutableSet<E> { var addCount:

    Int = 0 private set override fun add(element: E): Boolean { addCount++ return set.add(element) } override fun addAll(elements: Collection<E>): Boolean { addCount += elements.size return set.addAll(elements) } ... その他のコードは省略
  20. 試してみる val set = CountingSet(HashSet<Int>()) set.add(1) set.add(2) println(set.addCount) // 2

    set.addAll(setOf(3, 4, 5)) println(set.addCount) // 期待通りの5 実装をコンストラクタで渡す
  21. class CountingSet<E>(private val set: MutableSet<E>) : MutableSet<E> { var addCount:

    Int = 0 private set override fun add(element: E): Boolean { addCount++ return set.add(element) } override fun addAll(elements: Collection<E>): Boolean { addCount += elements.size return set.addAll(elements) } ... その他のコードは省略
  22. class CountingSet<E>(private val set: MutableSet<E>) : MutableSet<E> { var addCount:

    Int = 0 private set override fun add(element: E): Boolean { addCount++ return set.add(element) } override fun addAll(elements: Collection<E>): Boolean { addCount += elements.size return set.addAll(elements) } ... 他にオーバライドすべきメソッドたち
  23. override val size: Int get() = set.size override fun contains(element:

    E): Boolean = set.contains(element) override fun remove(element: E): Boolean = set.remove(element) override fun containsAll(elements: Collection<E>): Boolean = set.containsAll(elements) override fun isEmpty(): Boolean = set.isEmpty() override fun clear() { set.clear() } override fun iterator(): MutableIterator<E> = set.iterator() override fun removeAll(elements: Collection<E>): Boolean = set.removeAll(elements) override fun retainAll(elements: Collection<E>): Boolean = set.retainAll(elements) 他にオーバライドすべきメソッドたち
  24. override val size: Int get() = set.size override fun contains(element:

    E): Boolean = set.contains(element) override fun remove(element: E): Boolean = set.remove(element) override fun containsAll(elements: Collection<E>): Boolean = set.containsAll(elements) override fun isEmpty(): Boolean = set.isEmpty() override fun clear() { set.clear() } override fun iterator(): MutableIterator<E> = set.iterator() override fun removeAll(elements: Collection<E>): Boolean = set.removeAll(elements) override fun retainAll(elements: Collection<E>): Boolean = set.retainAll(elements) 他にオーバライドすべきメソッドたち めんど くさい!
  25. class CountingSet<E>(private val set: MutableSet<E>) : MutableSet<E> by set {

    var addCount: Int = 0 private set override fun add(element: E): Boolean { addCount++ return set.add(element) } override fun addAll(elements: Collection<E>): Boolean { addCount += elements.size return set.addAll(elements) } }
  26. class CountingSet<E>(private val set: MutableSet<E>) : MutableSet<E> by set {

    var addCount: Int = 0 private set override fun add(element: E): Boolean { addCount++ return set.add(element) } override fun addAll(elements: Collection<E>): Boolean { addCount += elements.size return set.addAll(elements) } } このおまじないが Class Delegation
  27. class CountingSet<E>(private val set: MutableSet<E>) : MutableSet<E> by set {

    var addCount: Int = 0 private set override fun add(element: E): Boolean { addCount++ return set.add(element) } override fun addAll(elements: Collection<E>): Boolean { addCount += elements.size return set.addAll(elements) } } ここは依然変わらず
  28. class CountingSet<E>(private val set: MutableSet<E>) : MutableSet<E> by set {

    var addCount: Int = 0 private set override fun add(element: E): Boolean { addCount++ return set.add(element) } override fun addAll(elements: Collection<E>): Boolean { addCount += elements.size return set.addAll(elements) } } 他にオーバライドすべきメソッドたち を明示的に記述する必要がない!
  29. 突然の宣伝 • Kotlinスタートブック (リックテレコム) • 目印は赤べこ • 7/17頃 発売 •

    360ページ • 今回の話のように 文法だけでなく、その 背景や周辺の事情に ついても言及しています