Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
KotlinのClass Delegationおさらい #Kotlin_Sansan
Search
Taro Nagasawa
July 01, 2016
Programming
1
2.7k
KotlinのClass Delegationおさらい #Kotlin_Sansan
第3回 Kotlin勉強会@Sansan(
http://connpass.com/event/33769/)で発表したスライドです
。
Taro Nagasawa
July 01, 2016
Tweet
Share
More Decks by Taro Nagasawa
See All by Taro Nagasawa
Android開発者のための Kotlin Multiplatform入門
ntaro
0
760
Kotlin 最新動向2022 #tfcon #techfeed
ntaro
1
2.3k
#Ubie 狂気の認知施策と選考設計
ntaro
13
13k
UbieにおけるサーバサイドKotlin活用事例
ntaro
1
1.1k
KotlinでSpring 完全理解ガイド #jsug
ntaro
6
3.5k
Kotlinでサーバサイドを始めよう!
ntaro
1
1k
Androidからサーバーサイドまで!プログラミング言語 Kotlinの魅力 #devboost
ntaro
5
2.8k
Kotlin Contracts #m3kt
ntaro
4
4.2k
How_to_Test_Server-side_Kotlin.pdf
ntaro
1
510
Other Decks in Programming
See All in Programming
MCPとデザインシステムに立脚したデザインと実装の融合
yukukotani
4
1.4k
Laravel Boost 超入門
fire_arlo
2
210
Tool Catalog Agent for Bedrock AgentCore Gateway
licux
6
2.3k
もうちょっといいRubyプロファイラを作りたい (2025)
osyoyu
1
410
ProxyによるWindow間RPC機構の構築
syumai
3
1.1k
Swift Updates - Learn Languages 2025
koher
2
470
そのAPI、誰のため? Androidライブラリ設計における利用者目線の実践テクニック
mkeeda
2
270
ソフトウェアテスト徹底指南書の紹介
goyoki
1
150
テストカバレッジ100%を10年続けて得られた学びと品質
mottyzzz
2
570
Azure SRE Agentで運用は楽になるのか?
kkamegawa
0
2k
Flutter with Dart MCP: All You Need - 박제창 2025 I/O Extended Busan
itsmedreamwalker
0
150
Kiroで始めるAI-DLC
kaonash
2
580
Featured
See All Featured
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
126
53k
The Power of CSS Pseudo Elements
geoffreycrofte
77
6k
Bash Introduction
62gerente
615
210k
Facilitating Awesome Meetings
lara
55
6.5k
The Cost Of JavaScript in 2023
addyosmani
53
8.9k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
31
2.2k
Balancing Empowerment & Direction
lara
3
620
Large-scale JavaScript Application Architecture
addyosmani
512
110k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
111
20k
Building a Modern Day E-commerce SEO Strategy
aleyda
43
7.6k
Gamification - CAS2011
davidbonilla
81
5.4k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.1k
Transcript
Kotlinの Class Delegation おさらい 2016-06-29 第3回Kotlin勉強会@Sansan 長澤 太郎 @ngsw_taro
差分プログ ラミング
差分プログ ラミング
Effective Java 項目16 「継承よりコンポジションを選ぶ」
Class Delegation が便利です
自己紹介 • 長澤 太郎 たろーって呼んでね • @ngsw_taro • プログラマー@エムスリー株式会社 ◦
Android, Kotlin, Java, Scala, Rubyなど • Kotlinエバンジェリスト(JetBrains黙認) ◦ 日本Kotlinユーザグループ代表 • やすべえとディズニーが好き
例題 要素が追加された 回数を記憶する Setを作成する。
差分プログラミング
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) } }
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) } } クラスの継承
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) } } 回数保持のプロパティ
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) } } 具象メソッドのオーバライド
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
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) } } 具象メソッドのオーバライド
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) } } カウント +要素数
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行!
試してみる val set = CountingHashSet<Int>() set.add(1) set.add(2) println(set.addCount) set.addAll(setOf(3, 4,
5)) println(set.addCount)
試してみる 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を呼び出している
試してみる val set = CountingHashSet<Int>() set.add(1) set.add(2) println(set.addCount) set.addAll(setOf(3, 4,
5)) println(set.addCount) // 5? 3つ追加している
試してみる val set = CountingHashSet<Int>() set.add(1) set.add(2) println(set.addCount) set.addAll(setOf(3, 4,
5)) println(set.addCount) // まさかの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) } } HashSet#addAllは addを呼び出す実装になっている なぜ期待通りに動かなかったのか
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) } } ここでカウントして なぜ期待通りに動かなかったのか
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の実装を呼び なぜ期待通りに動かなかったのか
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が呼び出されると、二重でカウント なぜ期待通りに動かなかったのか
どうすればいいか
どうすればいいか addAllでカウントしない
どうすればいいか addAllでカウントしない まぁ確かに...でも
どうすればいいか addAllでカウントしない まぁ確かに...でも スーパクラスの実装に依存、脆い
コンポジション
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) } ...
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) } ... インタフェースを実装
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) } ... このへんがコンポジション: 実装を継承するのではなく、 実装を保持する。
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) } ... さっきと同じ
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) } ... その他のコードは省略
試してみる 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 実装をコンストラクタで渡す
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) } ... その他のコードは省略
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) } ... 他にオーバライドすべきメソッドたち
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) 他にオーバライドすべきメソッドたち
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) 他にオーバライドすべきメソッドたち めんど くさい!
4. Class Delegation
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 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
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 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) } } 他にオーバライドすべきメソッドたち を明示的に記述する必要がない!
試してみる(コードはさっきと同じ) 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
まとめ • 実装の継承には十分注意する • インタフェースに依存し、実装は外部から注入 • Class Delegationを使うと、簡単に記述できる
突然の宣伝 • Kotlinスタートブック (リックテレコム) • 目印は赤べこ • 7/17頃 発売 •
360ページ • 今回の話のように 文法だけでなく、その 背景や周辺の事情に ついても言及しています
Thank you Enjoy Kotlin