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
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Taro Nagasawa
July 01, 2016
Programming
2.8k
1
Share
KotlinのClass Delegationおさらい #Kotlin_Sansan
第3回 Kotlin勉強会@Sansan(
http://connpass.com/event/33769/)で発表したスライドです
。
Taro Nagasawa
July 01, 2016
More Decks by Taro Nagasawa
See All by Taro Nagasawa
Android開発者のための Kotlin Multiplatform入門
ntaro
0
1.6k
Kotlin 最新動向2022 #tfcon #techfeed
ntaro
1
2.4k
#Ubie 狂気の認知施策と選考設計
ntaro
13
14k
UbieにおけるサーバサイドKotlin活用事例
ntaro
1
1.2k
KotlinでSpring 完全理解ガイド #jsug
ntaro
6
3.6k
Kotlinでサーバサイドを始めよう!
ntaro
1
1k
Androidからサーバーサイドまで!プログラミング言語 Kotlinの魅力 #devboost
ntaro
5
3k
Kotlin Contracts #m3kt
ntaro
4
4.4k
How_to_Test_Server-side_Kotlin.pdf
ntaro
1
560
Other Decks in Programming
See All in Programming
タクシーアプリ『GO』の バックエンド開発のおける AI利活用と若者のすべて
pyama86
3
1.8k
3Dシーンの圧縮
fadis
1
590
AI駆動開発で崩れていくコードベースを立て直す
kyoko_nr_nr
1
430
Claspは野良GASの夢をみるか
takter00
0
160
OSもどきOS
arkw
0
400
AI時代のUIはどこへ行く?その2!
yusukebe
19
6.5k
プラグインで拡張される Context をtype-safe にする難しさと設計判断
kazupon
2
570
oxlintはeslint/typescript-eslintを置き換えられるのか
shomafujita
2
310
AI時代の仕事技芸論 — ソフトウェア開発で「遊ぶように働く」職人的熟達のすすめ
kuranuki
1
610
Migrations : C'est une question d'hygiène !
vinceamstoutz
0
3.2k
「AIで開発し、AIを届ける」をEvalでつなぐ 〜AIネイティブに始めるプロダクト開発の実践〜 / Connecting "Develop with AI, deliver AI" with Eval
rkaga
4
2k
Swiftのレキシカルスコープ管理
kntkymt
0
210
Featured
See All Featured
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
62
54k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
720
Building Adaptive Systems
keathley
44
3k
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
Building a Scalable Design System with Sketch
lauravandoore
463
34k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.8k
Bioeconomy Workshop: Dr. Julius Ecuru, Opportunities for a Bioeconomy in West Africa
akademiya2063
PRO
1
130
sira's awesome portfolio website redesign presentation
elsirapls
0
270
Making the Leap to Tech Lead
cromwellryan
135
9.9k
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
180
Game over? The fight for quality and originality in the time of robots
wayneb77
1
190
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
2
840
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