Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ohtsuchi/0aebd381dbd05b3211409054bdd97777 to your computer and use it in GitHub Desktop.
Save ohtsuchi/0aebd381dbd05b3211409054bdd97777 to your computer and use it in GitHub Desktop.
Kotlinスタートブック読書勉強会 第10章 補足

Kotlinスタートブック読書勉強会 第10章 補足


reference や他のサイトなどに記述があって、赤べこ本では割愛されている(または ver1.1 以降の)内容の引用 が中心


1. Interface の 定義と実装

interface の method にも デフォルト引数 定義可能

// list 10.9 を 改修
interface Greeter {
    fun sayHello(target: String = "匿名")
}

class JapaneseGreeter : Greeter {
    override fun sayHello(target: String) {
        println("こんにちは, ${target}さん!")
    }
}

fun main(args: Array<String>) {
    val greeter = JapaneseGreeter()
    greeter.sayHello()           // こんにちは, 匿名さん!
    greeter.sayHello("たろう")   // こんにちは, たろうさん!
}
  • 第9章 の 補足 に記述したとおり, override 先で デフォルト引数 を指定するとエラー

2. デフォルト実装 と コンフリクトの回避


4. Delegation

list 10.12 class delegation を使った例

interface AListener {
    fun a1(); fun ab()
}
class AAdapter : AListener {
    override fun a1() = println("AAdapter:a1")
    override fun ab() = println("AAdapter:ab")
}

interface BListener {
    fun b1(); fun ab()
}
class BAdapter : BListener {
    override fun b1() = println("BAdapter:b1")
    override fun ab() = println("BAdapter:ab")
}

// ★ 複数 の class delegation
class MyListener(private val a: AListener, private val b: BListener) : AListener by a, BListener by b {
    override fun ab() { // `ab` の定義が衝突しているので override しないと コンパイルエラー
        b.ab()
    }
}

fun main(args: Array<String>) {
    val l = MyListener(AAdapter(), BAdapter())
    l.a1()  // AAdapter:a1
    l.b1()  // BAdapter:b1
    l.ab()  // BAdapter:ab
}

Effective java に掲載されている例 (項目16)

class InstrumentedHashSet<E> : HashSet<E>() {
    var addCount: Int = 0

    override fun add(e: E): Boolean {
        addCount++
        return super.add(e)
    }

    override fun addAll(c: Collection<E>): Boolean {
        addCount += c.size
        return super.addAll(c)
    }
}

fun main(args: Array<String>) {
    val s1 = InstrumentedHashSet<String>()
    s1.add("a")
    s1.add("b");
    println(s1.addCount)   // 2

    val s2 = InstrumentedHashSet<String>()
    s2.addAll(arrayOf("x", "y", "z"))
    println(s2.addCount)   // 6
}
  • 3 を期待していたのに 結果は 6
    • super.addAll の中で add が呼ばれているため

委譲に変更した例

// 変更したのは先頭行のみ. 他の実装は 継承の場合 と一緒
class InstrumentedHashSet<E>(private val s: MutableSet<E>) : MutableSet<E> by s {
    var addCount: Int = 0

    override fun add(e: E): Boolean {
        addCount++
        return s.add(e)
    }

    override fun addAll(c: Collection<E>): Boolean {
        addCount += c.size
        return s.addAll(c)
    }
}

fun main(args: Array<String>) {
    val s1 = InstrumentedHashSet(HashSet<String>()) // コンストラクタ で 委譲先 の インスタンス を渡す
    s1.add("a")
    s1.add("b");
    println(s1.addCount)   // 2

    val s2 = InstrumentedHashSet(HashSet<String>()) // 同上
    s2.addAll(arrayOf("x", "y", "z"))
    println(s2.addCount)   // 3
}

Effective java に掲載されている例 (項目17)

import java.time.LocalDateTime

fun Super.s() = println("... init start (${javaClass.kotlin.simpleName})")
fun Super.e() = println("... init end   (${javaClass.kotlin.simpleName})")
fun p() = println("-----------------------------")

abstract class Super {
    init {
        s()
        overrideMe() // ★[NG] コンストラクタ が override 可能なメソッドを呼び出し
        e()
    }
    abstract fun overrideMe()
}

class Sub : Super() {
    private var date = LocalDateTime.now()

    // ★ super クラス の init 呼び出し時点では `date` は まだ `null`
    override fun overrideMe() = println(date)
}

class Sub2 : Super() {
    private var date = LocalDateTime.now()

    init { // 親の init が 呼ばれた後, 実行される
        s()
        overrideMe() // sub クラス の init 呼び出し時点では `date` は 初期化済み
        e()
    }
    override fun overrideMe() = println(date)
}

fun main(args: Array<String>) {
    Sub()
    p()
    Sub2()
}
  • 実行結果
... init start (Sub)
null
... init end   (Sub)
-----------------------------
... init start (Sub2)
null
... init end   (Sub2)
... init start (Sub2)
2017-11-27T18:32:08.281
... init end   (Sub2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment