코틀린의 상속은 모든 class에서 가능한 것이 아니며 open으로 명시한 클래스만 가능하다. 예제를 보자.
open class Parent {
open fun show() {
println("Show: Parent class")
}
}
class Child: Parent() {
override fun show() {
println("Show: Child class")
}
}
fun main() {
val p1 = Parent()
val c1 = Child()
p1.show() // Show: Parent class
c1.show() // Show: Child class
}
그렇다면 open 키워드를 붙이지 않는다면 상속이 가능할까?
class StepParent {
open fun show() {
println("Show: Parent class")
}
}
class StepChild: StepParent() {} // compile error
StepParent 클래스는 final class 이기에 상속할 수 없다는 에러 메세지와 함께 에러가 난다.
정리하자면...
open 키워드를 명시하여 상속 할 수 있다.final 키워드를 명시해야한다. class의 기본 값은 final 이다.override 라는 키워드를 명시하면 부모 클래스의 동일한 이름의 메서드를 다르게 정의하겠다는 의미이다.
위의 예제 코드에도 존재하지만 다른 예제를 보며 알아보자.
open class Bird {
open fun twitter() {
println("Chirp Chirp")
}
}
final class Pigeon(): Bird() {
override fun twitter() {
println("Goo Goo")
}
}
final class Chicken(): Bird() {
override fun twitter() {
println("Cluck Cluck")
}
}
fun main() {
val pigeon = Pigeon()
val chicken = Chicken()
pigeon.twitter() // Goo Goo
chicken.twitter() // Cluck Cluck
}
분명 부모 클래스인 Bird의 open 메서드 twitter와는 다른 출력값이 출력된다.
메서드를 상속할 때, 인자가 다르면 안된다.
인자가 다른 것 뿐 아니라 오버로딩이 아닌 오버라이딩이기에 반환값, 인자의 순서 등 어느 하나라도 다르면 에러가 발생한다.
open class Gun {
open fun bang(bullet: String) {
println("$bullet Bang!")
}
}
final class Pistol: Gun() {
override fun bang() { // 부모 메서드와 인자의 개수가 달라 에러
println("This is pistol, Bang!")
}
}
protected 키워드를 사용하면, 상속 체계 밖에서 접근을 막는다.
open class Pokemon {
protected open fun showMe() {
println("Pokemon!")
}
}
final class Pikachu: Pokemon() {
override fun showMe() {
println("Pikachu!")
}
}
fun main() {
val poke = Pokemon()
val pika = Pikachu()
poke.showMe() // error
pika.showMe() // error
}