Skip to content

Instantly share code, notes, and snippets.

@ohtsuchi
Last active November 6, 2017 06:26
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/68ab430e50986124e0d5717143162572 to your computer and use it in GitHub Desktop.
Save ohtsuchi/68ab430e50986124e0d5717143162572 to your computer and use it in GitHub Desktop.
Kotlinスタートブック(赤べこ本) 第7章 の 写経

Kotlinスタートブック(赤べこ本) 第7章 の 写経

第7章 オブジェクトからクラスへ


1. Object の生成

list 7.1

  • object expression (オブジェクト式)
    • キーワード: object による オブジェクト生成の記法
  • -> 第13章-7 オブジェクト式 (p200) 参照
  • -> 第13章-8 オブジェクト宣言 (p202) 参照
fun main(args: Array<String>) {
    val bucket = object {
        // バケツの容量
        val capacity: Int = 5
        // 入っている水の量
        var quantity: Int = 0

        // バケツを水で満たす
        fun fill() {
            quantity = capacity
        }

        // 排水する
        fun drainAway() {
            quantity = 0
        }

        // 入っている水の量を出力する
        fun printQuantity() {
            println(quantity)
        }
    }

    bucket.printQuantity() // 0
    bucket.fill()
    bucket.printQuantity() // 5
    bucket.drainAway()
    bucket.printQuantity() // 0
}

2. Interface

list 7.2 interface Bucket

  • interface Bucket を追加
    • 中の定義は空
  • object expression で Bucket を 実装
    • pourTo(Bucket) メソッド追加
      • 中の実装は空
interface Bucket // <追加>

fun main(args: Array<String>) {
    val bucket = object : Bucket {
        // バケツの容量
        val capacity: Int = 5
        // 入っている水の量
        var quantity: Int = 0

        // バケツを水で満たす
        fun fill() {
            quantity = capacity
        }

        // 排水する
        fun drainAway() {
            quantity = 0
        }

        // 入っている水の量を出力する
        fun printQuantity() {
            println(quantity)
        }
        
        // 別のバケツに注ぐ <追加>
        fun pourTo(that: Bucket) {
            // TODO 未実装
        }
    }

    bucket.printQuantity() // 0
    bucket.fill()
    bucket.printQuantity() // 5
    bucket.drainAway()
    bucket.printQuantity() // 0
}

list 7.3 interface Bucket に メソッド をまとめ, list 7.4 関数 createBucket 作成, list 7.5

  • interface Bucket に バケツオブジェクト が提供すべき メソッド をまとめる
    • fill()
    • drainAway()
    • pourTo(Bucket)
    • printQuantity() メソッドは削除
    • getCapacity(): Int
    • getQuantity(): Int
    • setQuantity(Int)
    • Intellij 使用の場合は
      • リファクタリング機能で fill(), drainAway(), pourTo(Bucket) を抽出可能
      • Ctrl + t(Refactor This) -> Pull Members Up
        • または Cmd + Shift + a 押してから Pull Members Up と入力
        • または Shift2回 押してから Pull Members Up と入力
      • 対象のメソッドを選択 -> Refactor ボタン
  • object : Bucket 作成ロジックを main から外出し
    • 関数 createBucket(Int): Bucket 作成
// list 7.3
interface Bucket {
    fun fill()
    fun drainAway()
    fun pourTo(that: Bucket)

    fun getCapacity(): Int           // 容量(変更できない値) にアクセス するメソッド
    fun getQuantity(): Int           // 水の量 にアクセス するメソッド
    fun setQuantity(quantity: Int)   // 同上
}

// list 7.4
fun createBucket(capacity: Int): Bucket = object : Bucket {
    var _quantity: Int = 0

    override fun fill() {
        setQuantity(getCapacity())
    }

    override fun drainAway() {
        setQuantity(0)
    }

    // このバケツ(this) から あのバケツ(that) へ可能な限り水を注ぐ
    override fun pourTo(that: Bucket) {
        val thatVacuity = that.getCapacity() - that.getQuantity()
        if (getQuantity() <= thatVacuity) { // this の 水の量 <= that の 空き容量 であれば, this の水を that に全て注ぐ事ができる
            that.setQuantity(that.getQuantity() + getQuantity())
            drainAway()
        } else {
            that.fill()
            setQuantity(getQuantity() - thatVacuity)
        }
    }

    override fun getCapacity(): Int = capacity

    override fun getQuantity(): Int = _quantity
    override fun setQuantity(quantity: Int) {
        _quantity = quantity
    }
}

// list 7.5
fun main(args: Array<String>) {
    // capacity = 7 のバケツを作る
    val bucket1 = createBucket(7)
    // capacity = 4 のバケツを作る
    val bucket2 = createBucket(4)

    // バケツ1 を満たす
    bucket1.fill()
    // バケツ1 から バケツ2 へ可能な限り水を注ぐ
    bucket1.pourTo(bucket2)

    println(bucket1.getQuantity()) // 3
    println(bucket2.getQuantity()) // 4
}

3. Property

list 7.6 get〜, set〜 を Property に変更, list 7.7 override val, override var

// list 7.6
interface Bucket {
    fun fill()
    fun drainAway()
    fun pourTo(that: Bucket)

    val capacity: Int // <Property>
    var quantity: Int // <Property>
}

// list 7.7
fun createBucket(_capacity: Int): Bucket = object : Bucket {
    override val capacity = _capacity  // `override val`
    override var quantity = 0          // `override var`

    override fun fill() {
        quantity = capacity
    }

    override fun drainAway() {
        quantity = 0
    }

    override fun pourTo(that: Bucket) {
        val thatVacuity = that.capacity - that.quantity
        if (quantity <= thatVacuity) {
            that.quantity += quantity
            drainAway()
        } else {
            that.fill()
            quantity -= thatVacuity
        }
    }
}

// list 7.5 改修(getQuantity() -> quantity)
fun main(args: Array<String>) {
    val bucket1 = createBucket(7)
    val bucket2 = createBucket(4)

    bucket1.fill()
    bucket1.pourTo(bucket2)

    println(bucket1.quantity) // 3
    println(bucket2.quantity) // 4
}

4. Class

list 7.8 Class に変更, list 7.9

// list 7.6
interface Bucket {
    fun fill()
    fun drainAway()
    fun pourTo(that: Bucket)

    val capacity: Int
    var quantity: Int
}

// list 7.8 <Class>
class BucketImpl(_capacity: Int) : Bucket {
    override val capacity = _capacity
    override var quantity = 0

    override fun fill() {
        quantity = capacity
    }

    override fun drainAway() {
        quantity = 0
    }

    override fun pourTo(that: Bucket) {
        val thatVacuity = that.capacity - that.quantity
        if (quantity <= thatVacuity) {
            that.quantity += quantity
            drainAway()
        } else {
            that.fill()
            quantity -= thatVacuity
        }
    }
}

// list 7.9
fun main(args: Array<String>) {
    val bucket1 = BucketImpl(7)
    val bucket2 = BucketImpl(4)

    bucket1.fill()
    bucket1.pourTo(bucket2)

    println(bucket1.quantity) // 3
    println(bucket2.quantity) // 4
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment