🌳 상속
📖 상속이란?
**상속(Inheritance)**은 기존 클래스의 기능을 물려받아 새로운 클래스를 만드는 것입니다. 코드 재사용과 확장에 유용합니다.
💡 기본 상속
open 키워드
Kotlin 클래스는 기본적으로 final입니다. 상속하려면 open 키워드 필요!
// open - 상속 가능
open class Animal(val name: String) {
open fun sound() {
println("동물 소리")
}
}
// : 로 상속
class Dog(name: String) : Animal(name) {
override fun sound() {
println("멍멍!")
}
}
fun main() {
val dog = Dog("바둑이")
println(dog.name) // 바둑이
dog.sound() // 멍멍!
}
상속 규칙
open class Animal(val name: String)
// ✅ open 클래스는 상속 가능
class Dog(name: String) : Animal(name)
// ❌ 일반 클래스는 상속 불가
class Cat(val name: String) // final (기본값)
// class Kitten : Cat("야옹이") // 오류!
🔧 메서드 오버라이딩
기본 오버라이딩
open class Animal(val name: String) {
open fun eat() {
println("$name가 먹습니다")
}
open fun sleep() {
println("$name가 잡니다")
}
}
class Dog(name: String) : Animal(name) {
// 메서드 재정의
override fun eat() {
println("$name가 사료를 먹습니다")
}
// 추가 메서드
fun bark() {
println("멍멍!")
}
}
fun main() {
val dog = Dog("바둑이")
dog.eat() // 바둑이가 사료를 먹습니다
dog.sleep() // 바둑이가 잡니다 (부모 메서드)
dog.bark() // 멍멍!
}
super 키워드
부모 클래스의 메서드 호출:
open class Animal(val name: String) {
open fun eat() {
println("$name가 먹습니다")
}
}
class Dog(name: String) : Animal(name) {
override fun eat() {
super.eat() // 부모 메서드 호출
println("꼬리를 흔듭니다")
}
}
fun main() {
val dog = Dog("바둑이")
dog.eat()
// 바둑이가 먹습니다
// 꼬리를 흔듭니다
}
🎯 프로퍼티 오버라이딩
프로퍼티 재정의
open class Animal {
open val type: String = "동물"
}
class Dog : Animal() {
override val type: String = "개"
}
class Cat : Animal() {
override val type: String = "고양이"
}
fun main() {
val dog = Dog()
val cat = Cat()
println(dog.type) // 개
println(cat.type) // 고양이
}
생성자에서 오버라이드
open class Animal(open val type: String)
class Dog(override val type: String = "개") : Animal(type)
fun main() {
val dog = Dog()
println(dog.type) // 개
}
🎨 추상 클래스
abstract 키워드
// 추상 클래스 (인스턴스 생성 불가)
abstract class Shape {
abstract val name: String
abstract fun area(): Double
// 일반 메서드도 가능
fun describe() {
println("도형: $name, 면적: ${area()}")
}
}
class Circle(val radius: Double) : Shape() {
override val name: String = "원"
override fun area(): Double {
return Math.PI * radius * radius
}
}
class Rectangle(val width: Double, val height: Double) : Shape() {
override val name: String = "직사각형"
override fun area(): Double {
return width * height
}
}
fun main() {
val circle = Circle(5.0)
val rectangle = Rectangle(4.0, 6.0)
circle.describe() // 도형: 원, 면적: 78.54
rectangle.describe() // 도형: 직사각형, 면적: 24.0
}