추상 클래스
Coddy Kotlin 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 57개 중 20번째.
abstract 클래스는 자체적으로 인스턴스화할 수 없는 상위 클래스입니다. 본문 없이 abstract 멤버를 선언할 수 있으며, 모든 구체 클래스는 이러한 멤버를 구현해야 합니다:
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
}main 내부에서:
val shapes: List<Shape> = listOf(Circle(1.0), Rect(2.0, 3.0))
for (s in shapes) println(s.describe())출력:
circle with area 3.14
rect with area 6.0추상 클래스는 open 키워드가 없어도 open이며, 그 추상 멤버도 open이므로 서브클래스에서는 override만 작성하면 됩니다. 추상 클래스 자체를 생성하려고 하면 컴파일되지 않으며, 추상 멤버를 구현하지 않은 서브클래스 역시 추상 클래스여야 합니다. 슈퍼클래스의 일부 멤버에 대해 자체적으로 적절한 동작을 정의할 수 없을 때 추상 클래스를 사용하세요:
// val s = Shape("blob") // 오류: 추상 클래스의 인스턴스를 생성할 수 없습니다
// class Blob : Shape("blob") // 오류: Blob이 area()를 구현하지 않습니다
abstract class Polygon(name: String) : Shape(name) // 괜찮음: 여전히 추상추상 클래스는 생성자, 상태 및 일반 메서드를 가질 수 있으며, 서브클래스는 이를 상속합니다. 일반적인 사용 사례는 단계가 달라지는 고정된 절차인 템플릿 메서드입니다. 슈퍼클래스 메서드가 단계들을 실행하고, 서브클래스가 추상 메서드의 구현을 작성합니다:
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"
}main 내부에서:
println(Sales(420).render())
println(Stock(17).render())출력:
== Sales ==
total: 420
(end)
== Stock ==
items: 17
(counted today)추상 프로퍼티도 같은 방식으로 작동합니다. 서브클래스는 생성자 프로퍼티, 저장 프로퍼티 또는 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
}main 내부:
val staff = listOf(Salaried("Ada", 4000), Hourly("Bo", 80, 25))
for (w in staff) println("${w.name}: ${w.yearly()}")출력:
Ada: 48000
Bo: 24000챌린지
쉬움Discount는 추상 클래스입니다. 추상 메서드 amount(price)를 선언하고 apply(price)를 구현합니다. 이 메서드는 가격에서 amount(price)를 뺀 값을 반환하지만, 결과가 0보다 작아지지는 않습니다. 서브클래스를 완성하세요: PercentOff(percent)는 가격의 해당 백분율만큼을 할인하고(내림 처리), FixedOff(value)는 고정된 값을 할인하며, SpendMore(threshold, off)는 가격이 최소한 threshold일 때만 off를 할인합니다.
제공된 코드는 가격을 읽은 다음 p,10, f,300 또는 s,500,50으로 할인 정보를 읽고, 각각을 가격에 적용한 후 1000 -> 900을 출력합니다.
코드는 Discount.kt, PercentOff.kt, FixedOff.kt 및 SpendMore.kt에 작성하세요. Main.kt에는 제공된 입력/출력 코드가 들어 있으며 수정할 수 없습니다.
직접 해보기
fun main() {
// 제공된 입/출력 코드: 그대로 유지하세요
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)}")
}
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
직접 연습해 보세요: Kotlin 플레이그라운드