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.6k
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
Kotlin 最新動向2022 #tfcon #techfeed
ntaro
1
2k
#Ubie 狂気の認知施策と選考設計
ntaro
13
12k
UbieにおけるサーバサイドKotlin活用事例
ntaro
1
1k
KotlinでSpring 完全理解ガイド #jsug
ntaro
6
3.2k
Kotlinでサーバサイドを始めよう!
ntaro
1
850
Androidからサーバーサイドまで!プログラミング言語 Kotlinの魅力 #devboost
ntaro
5
2.3k
Kotlin Contracts #m3kt
ntaro
4
3.5k
How_to_Test_Server-side_Kotlin.pdf
ntaro
1
390
Kotlin Fest 2018 - Opening session
ntaro
0
4.2k
Other Decks in Programming
See All in Programming
⼤規模⾔語モデルの拡張(RAG)が 終わったかも知れない件について
nearme_tech
23
15k
エンターテイメント業界で利用されるAWS
demuyan
0
210
Git Rebase
bkuhlmann
11
1.6k
効率化に挑戦してみたらモバイル開発が少し快適になった話
ryunakayama
0
130
はてなにおける CSS Modules、及び CSS Modules に足りないもの / CSS Modules in Hatena, and CSS Modules missing parts
mizdra
7
940
見た目から始める生産性向上
ikumatadokoro
7
850
Komplexe Oberflächen mit SVG und der Web Animation API
joergneumann
0
670
Milestoner
bkuhlmann
1
410
Let's learn code review
riofujimon
2
420
障害対応を起点としたもっといい開発と運用のサイクル作りのためにできること / Hatena Enginner Seminar #29
polamjag
0
180
Prepare for Jakarta EE 11 - Performance and Developer Productivity
ivargrimstad
0
810
二郎系ラーメンのコールで学ぶ AST 解析
memory1994
PRO
7
1.7k
Featured
See All Featured
Large-scale JavaScript Application Architecture
addyosmani
504
110k
Into the Great Unknown - MozCon
thekraken
10
990
VelocityConf: Rendering Performance Case Studies
addyosmani
320
23k
Unsuck your backbone
ammeep
663
57k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
221
21k
What's in a price? How to price your products and services
michaelherold
237
11k
Side Projects
sachag
451
41k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
7
1k
How to name files
jennybc
65
93k
For a Future-Friendly Web
brad_frost
172
9k
We Have a Design System, Now What?
morganepeng
43
6.8k
Why You Should Never Use an ORM
jnunemaker
PRO
51
8.6k
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