자바에서는 final로 명시적으로 상속을 금지하지 않는 모든 클래스를 다른 클래스가 상속할 수 있습니다. 기본적으로 상속이 가능하면 편리한 경우도 많지만 문제가 생기는 경우도 많습니다.
취약한 기반 클래스 문제는 하위 클래스가 기반 클래스에 대해 가졌던 가정이 기반 클래스를 변경함으로써 깨져버린 경우에 발생합니다. 어떤 클래스가 자신을 상속하는 방법에 대해 정확한 규칙(어떤 메소드를 어떻게 오버라이드해야 하는지 등)을 제공하지 않는다면 그 클래스의 클라이언트는 기반 클래스를 작성한 사람의 의도와 다른 방식으로 메소드를 오버라이드할 위험이 있습니다.
모든 하위 클래스를 분석하는 것은 불가능하므로 기반 클래스를 변경하는 경우 하위 클래스의 동작이 예기치 않게 바뀔 수도 있다는면에서 기반 클래스는 취약합니다.
자바 프로그래밍 기법에 대한 책 중 가장 유명한 책인 조슈아 블로크가 쓴 『EffectiveJava』에서는 “상속을 위한 설
계와 문서를 갖추거나, 그럴 수 없다면 상속을 금지하라”라는 조언을 합니다. 이는 특별히 하위 클래스에서 오버라이드하게 의도된 클래스와 메소드가 아니라면 모두 final로 만들라는 뜻입니다.
코틀린도 마찬가지 철학을 따른다. 자바의 클래스와 메소드는 기본적으로 상속에 대해 열려있지만 코틀린의 클래스와 메소드는 기본적으로 final입니다. 어떤 클래스의 상속을 허용하려면 클래스 앞에 open 변경자를 붙여야 합니다. 그와 더불어 오버라이드를 허용하고 싶은 메소드나 프로퍼티의 앞에도 open 변경자를 붙여야 합니다.
class A : B {
// final인 상태로 하위 클래스가 이 함수를 오버라이드 할 수 없습니다.
fun a() { ... }
// open인 상태로 하위 클래스가 이 함수를 오버라이드 할 수 있습니다.
open fun b() { ... }
// 기본적으로 오버라이드된 함수는 열려있는 상태입니다.
override fun c() { ... }
// 상위 클래스에서 오버라이드한 함수앞에 final을 붙이면 상속 받은 하위 클래스가 오버라이드 할 수 없습니다.
final override fun d() { ... }
}
클래스의 기본적인 상속 가능 상태를 final로 함으로써 얻을 수 있는 큰 이익은 다양한 경우에 스마트 캐스트가 가능하다는 점입니다. 스마트 캐스트는 타입 검사 뒤에 변경될 수 없는 변수에만 적용 가능합니다. 클래스 프로퍼티의 경우 이는 val이면서 커스텀 접근자가 없는 경우에만 스마트 캐스트를 쓸 수 있다는 의미입니다.
abstract로 선언한 추상 클래스는 인스턴스화 할 수 없습니다. 추상 클래스에는 구현이 없는 추상 멤버가 있기
때문에 하위 클래스에서 그 추상 멤버를 오버라이드해야만 하는 게 보통입니다. 추상 멤버는 항상 열려기 때문에 open 변경자를 명시할 필요가 없습니다.
abstract class A {
fun a() { ... }
override fun b() { ... }
abstract fun c() { ... }
}
open과 abstract의 차이는 open은 '할 수 있는 것'이고, abstract는 '반드시 해야 하는 것'의 차이라고 볼 수 있습니다.
[ 출처 : Kotlin In Action ]
'Language > Kotlin In Action' 카테고리의 다른 글
[Kotlin In Action] 코틀린이란? (0) | 2021.09.29 |
---|---|
[Kotlin In Action] 인터페이스 (0) | 2021.04.22 |
[Kotlin In Action] 가변 인자 (0) | 2021.04.22 |
[Kotlin In Action] 확장함수 (0) | 2021.04.21 |
[Kotlin In Action] 문자열 템플릿 (0) | 2021.04.13 |
댓글