- 상속 관련 키워드 정리
- final: override를 할 수 없게 한다. default로 보이지 않게 존재
- open: override를 열어 준다
- abstract: 반드시 override 해야 한다
- override: 상위 타입을 오버라이드 하고 있다
- 상속 방법
코틀린에서는 상속 받을 때 ':'를 사용하여 선언한다
abstract class Animal(
protected val species: String,
protected val legCount: Int
) {
abstract fun move()
}
class Cat(
species: String
) : Animal(species, 4) {
override fun move() {
println("고양이 걸음")
}
}
변수 타입 선언과 다르게 한칸 띄고 :를 사용
()를 통해 상속과 동시에 super를 호출할 수 있음
추상 멤버가 아니면 기본적으로는 오버라이드가 불가능하다
getLegCount 오버라이드 시
legCount에 custom getter 구현을 위해서는 open 예약어를 붙여야만 구현이 가능하다
abstract class Animal(
protected val species: String,
protected open val legCount: Int
) {
abstract fun move()
}
class Penguin(
species: String
) : Animal(species, 2){
private val wingCount: Int = 2
override fun move() {
println("펭귄 걸음")
}
override val legCount: Int
get() = super.legCount + this.wingCount
}
- 인터페이스를 함께 상속 받는 경우
추상클래스를 상속받을 때와 마찬가지로 상속 받으면 된다
,로 구분하여 추가 가능
interface Flyable {
fun act() {
println("파닥 파닥")
}
}
interface Swimable {
val swimAbility: Int // 상속받은 객체에서 getter 구현을 원한다는 의미
fun act() {
println("어푸 어푸")
}
}
class Penguin(
species: String
) : Animal(species, 2), Swimable, Flyable {
private val wingCount: Int = 2
override fun move() {
println("펭귄 걸음")
}
override val legCount: Int
get() = super.legCount + this.wingCount
override fun act() {
super<Swimable>.act()
super<Flyable>.act()
}
override val swimAbility: Int
get() = 3
}
인터페이스 예시가 조금 이상하지만.. 같은 메서드를 동시에 상속 받아 구현할 때의 예시를 보여주기 위한 예시 같다
우선 예제를 살펴보면 super<클래스명>.act() 를 통해 상속받은 객체의 메서드를 호출할 수 있다
- 상속 시 주의할 점
fun main() {
Derived(300)
}
open class Base(
open val number: Int = 100
) {
init {
println("Base Class")
println(number)
}
}
class Derived(
override val number: Int
) : Base(number) {
init {
println("Derived Class")
}
}
위 코드를 실행 시켜보면 아래와 같은 결과를 얻을 수 있다
Base Class
0
Derived Class
override를 통해 Derived 에서 300 값을 number에 넣어서 출력하고 싶었는데 원하는대로 결과가 나오지 않고
기대 값 300이 아닌 결과 값 0이 출력되는 것을 알 수 있다
100도 아니고 300도 아닌 0이 출력되는 이유는 무엇일까?
실행 순서를 보면 답을 알 수 있다
Base Class가 먼저 출력되고 Derived Class가 출력되었다
상위 클래스의 init가 먼저 실행되고 그 다음 하위클래스의 init가 실행된 것 이다
상위 클래스인 Base가 실행되는 동안 Derived에서는 아직 number 값이 초기화되지 않은 상태고
Base에서 number 값을 출력하게 되면 하위 클래스인 Derived 클래스에서 number 값을 가져오게 되는데
값이 존재하지 않으니 int의 기초값인 0이 출력되는 것이다
즉, 상위 클래스에 constructor와 init에서는 하위 클래스의 필드에 접근하면 안된다
final이 아닌 필드에 접근하면 안된다는 것!
하위 클래스에서 오버라이드하고 있는 필드에는 접근하면 안된다
상위 클래스를 설계할 때
생성자 또는 초기화 블록에 사용되는 프로퍼티에는 open을 피해야 한다
'개발 지식 > 자바 개발자를 위한 코틀린 입문' 카테고리의 다른 글
자바 개발자를 위한 코틀린 입문 - 다양한 함수 (0) | 2023.08.10 |
---|---|
자바 개발자를 위한 코틀린 입문 - Sealed Class (0) | 2023.08.09 |
자바 개발자를 위한 코틀린 입문 - 동일성/동등성 비교 방법 (0) | 2023.08.07 |
자바 개발자를 위한 코틀린 입문 - Kotlin의 특이한 타입 3가지 (0) | 2023.08.07 |
자바 개발자를 위한 코틀린 입문 - null 처리 방법 (0) | 2023.08.07 |