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
370
Kotlin 最新動向2022 #tfcon #techfeed
ntaro
1
2.1k
#Ubie 狂気の認知施策と選考設計
ntaro
13
12k
UbieにおけるサーバサイドKotlin活用事例
ntaro
1
1.1k
KotlinでSpring 完全理解ガイド #jsug
ntaro
6
3.3k
Kotlinでサーバサイドを始めよう!
ntaro
1
920
Androidからサーバーサイドまで!プログラミング言語 Kotlinの魅力 #devboost
ntaro
5
2.6k
Kotlin Contracts #m3kt
ntaro
4
3.8k
How_to_Test_Server-side_Kotlin.pdf
ntaro
1
430
Other Decks in Programming
See All in Programming
as(型アサーション)を書く前にできること
marokanatani
10
2.7k
AWS Lambdaから始まった Serverlessの「熱」とキャリアパス / It started with AWS Lambda Serverless “fever” and career path
seike460
PRO
1
260
Enabling DevOps and Team Topologies Through Architecture: Architecting for Fast Flow
cer
PRO
0
340
Remix on Hono on Cloudflare Workers
yusukebe
1
300
CSC509 Lecture 09
javiergs
PRO
0
140
3 Effective Rules for Using Signals in Angular
manfredsteyer
PRO
0
100
Jakarta EE meets AI
ivargrimstad
0
260
Kaigi on Rails 2024 〜運営の裏側〜
krpk1900
1
250
Nurturing OpenJDK distribution: Eclipse Temurin Success History and plan
ivargrimstad
0
1k
3 Effective Rules for Using Signals in Angular
manfredsteyer
PRO
0
120
광고 소재 심사 과정에 AI를 도입하여 광고 서비스 생산성 향상시키기
kakao
PRO
0
170
レガシーシステムにどう立ち向かうか 複雑さと理想と現実/vs-legacy
suzukihoge
14
2.3k
Featured
See All Featured
Put a Button on it: Removing Barriers to Going Fast.
kastner
59
3.5k
Raft: Consensus for Rubyists
vanstee
136
6.6k
Rails Girls Zürich Keynote
gr2m
94
13k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
506
140k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
25
1.8k
Thoughts on Productivity
jonyablonski
67
4.3k
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
A Modern Web Designer's Workflow
chriscoyier
693
190k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
280
13k
5 minutes of I Can Smell Your CMS
philhawksworth
202
19k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
6
430
GraphQLとの向き合い方2022年版
quramy
43
13k
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