Menu
CoddyTech

Kelas Abstrak

Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan Kotlin di Coddy. Pelajaran 20 dari 57.

Class abstract adalah superclass yang tidak dapat dibuat menjadi instance dengan sendirinya. Class ini dapat mendeklarasikan member abstract tanpa body, dan setiap subclass konkret harus mengimplementasikannya:

abstract class Shape(val name: String) {
    abstract fun area(): Double

    fun describe() = "$name with area ${area()}"
}
class Circle(val r: Double) : Shape("circle") {
    override fun area() = 3.14 * r * r
}
class Rect(val w: Double, val h: Double) : Shape("rect") {
    override fun area() = w * h
}

Di dalam main:

val shapes: List<Shape> = listOf(Circle(1.0), Rect(2.0, 3.0))
for (s in shapes) println(s.describe())

Output:

circle with area 3.14
rect with area 6.0

Abstract class bersifat open tanpa kata kunci open, dan member abstract-nya juga bersifat open, jadi subclass hanya menulis override. Membuat abstract class itu sendiri tidak bisa dikompilasi, dan subclass yang tidak menyertakan member abstract juga harus abstract. Gunakan abstract class saat superclass tidak memiliki perilaku yang masuk akal untuk beberapa member:

// val s = Shape("blob")                       // error: tidak dapat membuat instance dari class abstrak
// class Blob : Shape("blob")                  // error: Blob tidak mengimplementasikan area()
abstract class Polygon(name: String) : Shape(name)   // boleh: masih abstrak

Sebuah class abstrak dapat memiliki constructor, state, dan method biasa yang diwarisi subclass. Salah satu kegunaan umum adalah prosedur tetap yang langkah-langkahnya bervariasi, yaitu template method: method superclass menjalankan langkah-langkahnya, dan subclass mengisi bagian yang abstrak:

abstract class Report(val title: String) {
    fun render() = "== $title ==\n${body()}\n(${footer()})"

    abstract fun body(): String
    open fun footer() = "end"
}
class Sales(val total: Int) : Report("Sales") {
    override fun body() = "total: $total"
}
class Stock(val items: Int) : Report("Stock") {
    override fun body() = "items: $items"
    override fun footer() = "counted today"
}

Di dalam main:

println(Sales(420).render())
println(Stock(17).render())

Output:

== Sales ==
total: 420
(end)
== Stock ==
items: 17
(counted today)

Property abstrak bekerja dengan cara yang sama. Subclass menyediakan nilainya sebagai property constructor, stored property, atau getter:

abstract class Worker(val name: String) {
    abstract val monthly: Int
    fun yearly() = monthly * 12
}
class Salaried(name: String, override val monthly: Int) : Worker(name)
class Hourly(name: String, val hours: Int, val rate: Int) : Worker(name) {
    override val monthly: Int
        get() = hours * rate
}

Di dalam main:

val staff = listOf(Salaried("Ada", 4000), Hourly("Bo", 80, 25))
for (w in staff) println("${w.name}: ${w.yearly()}")

Output:

Ada: 48000
Bo: 24000
challenge icon

Tantangan

Mudah

Discount adalah class abstrak. Class ini mendeklarasikan method abstrak amount(price) dan mengimplementasikan apply(price), yang mengembalikan harga dikurangi amount(price), tetapi tidak pernah kurang dari 0. Lengkapi subclass berikut: PercentOff(percent) mengambil persentase tersebut dari harga (dibulatkan ke bawah), FixedOff(value) mengambil nilai tetap, dan SpendMore(threshold, off) mengambil off hanya jika harga setidaknya threshold.

Code yang disediakan membaca harga, lalu diskon p,10, f,300 atau s,500,50, menerapkan masing-masing diskon pada harga, lalu mencetak 1000 -> 900.

Tulis kodemu di Discount.kt, PercentOff.kt, FixedOff.kt dan SpendMore.kt. Main.kt berisi code input/output yang disediakan dan tidak boleh diedit.

Coba sendiri

fun main() {
    // Kode input/output yang disediakan: biarkan apa adanya
    val input = generateSequence(::readLine).toList()
    val price = input[0].toInt()
    for (line in input.drop(1)) {
        val p = line.split(",")
        val discount: Discount = when (p[0]) {
            "p" -> PercentOff(p[1].toInt())
            "f" -> FixedOff(p[1].toInt())
            else -> SpendMore(p[1].toInt(), p[2].toInt())
        }
        println("$price -> ${discount.apply(price)}")
    }
}
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Objek

Latihan sendiri: Playground Kotlin