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
690
Kotlin 最新動向2022 #tfcon #techfeed
ntaro
1
2.2k
#Ubie 狂気の認知施策と選考設計
ntaro
13
13k
UbieにおけるサーバサイドKotlin活用事例
ntaro
1
1.1k
KotlinでSpring 完全理解ガイド #jsug
ntaro
6
3.4k
Kotlinでサーバサイドを始めよう!
ntaro
1
990
Androidからサーバーサイドまで!プログラミング言語 Kotlinの魅力 #devboost
ntaro
5
2.7k
Kotlin Contracts #m3kt
ntaro
4
4.1k
How_to_Test_Server-side_Kotlin.pdf
ntaro
1
500
Other Decks in Programming
See All in Programming
Railsアプリケーションと パフォーマンスチューニング ー 秒間5万リクエストの モバイルオーダーシステムを支える事例 ー Rubyセミナー 大阪
falcon8823
5
1.1k
初学者でも今すぐできる、Claude Codeの生産性を10倍上げるTips
s4yuba
16
11k
The Modern View Layer Rails Deserves: A Vision For 2025 And Beyond @ RailsConf 2025, Philadelphia, PA
marcoroth
2
400
Is Xcode slowly dying out in 2025?
uetyo
1
280
状態遷移図を書こう / Sequence Chart vs State Diagram
orgachem
PRO
1
120
Python型ヒント完全ガイド 初心者でも分かる、現代的で実践的な使い方
mickey_kubo
1
130
Azure AI Foundryではじめてのマルチエージェントワークフロー
seosoft
0
180
Goで作る、開発・CI環境
sin392
0
240
Advanced Micro Frontends: Multi Version/ Framework Scenarios @WAD 2025, Berlin
manfredsteyer
PRO
0
160
ペアプロ × 生成AI 現場での実践と課題について / generative-ai-in-pair-programming
codmoninc
2
18k
PipeCDのプラグイン化で目指すところ
warashi
1
280
10 Costly Database Performance Mistakes (And How To Fix Them)
andyatkinson
0
400
Featured
See All Featured
The Invisible Side of Design
smashingmag
301
51k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
18
970
Product Roadmaps are Hard
iamctodd
PRO
54
11k
Optimizing for Happiness
mojombo
379
70k
Mobile First: as difficult as doing things right
swwweet
223
9.7k
Faster Mobile Websites
deanohume
307
31k
Intergalactic Javascript Robots from Outer Space
tanoku
271
27k
Building a Scalable Design System with Sketch
lauravandoore
462
33k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
50
5.5k
Facilitating Awesome Meetings
lara
54
6.4k
It's Worth the Effort
3n
185
28k
Gamification - CAS2011
davidbonilla
81
5.4k
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