7. 상속
1) Any 클래스
- 모든 클래스는 Any 클래스의 서브 클래스
- Any 클래스는 java.lang.Object 클래스와 달리 equals(), toString()을 제외한 다른 멤버들을 제공하지 않음
2) 상속을 통한 클래스 정의
- 클래스 정의시 다른 클래스를 상속받으면 정의된 멤버를 사용 가능
- open 예약어를 통해 상속이 허용된 클래스만 상속 가능
- 클래스 선언시 ':클래스명()' 의 형태로 상속
open class Parent constructor(val pr: String = "init"){
fun hello() = println("Hello $pr")
}
class Child constructor(name: String): Parent(name){
fun say() = println("My name is $pr")
}
fun main() {
val child = Child("John")
child.hello()
child.say()
}
// 결과
Hello John
My name is John
3) 오버라이드
- 상위 클래스에 정의된 프로퍼티나 함수를 하위 클래스에서 재정의하는 것
- open 예약어를 통해 오버라이딩이 허용된 프로퍼티나 함수만 상속 가능
- final 예약어와 함께 선언된 경우 오버라이딩 불가
- override 예약어를 통해 구현
- override 예약어는 open 예약어가 포함되어있어서 하위 클래스에서 상속 가능(final을 추가해서 금지 가능)
- 프로퍼티 오버라이딩 제약조건
동일한 이름과 타입만 가능
val -> val, var 가능 / var -> var만 가능
(타입)? -> (타입)?, (타입) 가능 / (타입) -> (타입)만 가능 (*null 불허 -> 허용 불가)
open class ParentClass{
open val parentProperty: String = "parentProperty"
get() = field + " from ParentClass"
open fun parentFunction(){
println("Hello from ParentClass")
}
}
class ChildClass: ParentClass(){
override var parentProperty: String = "parentProperty"
get() = field + " from ChildClass"
override fun parentFunction(){
println("Hello from ChildClass")
}
fun useSuper(){
println("######### useSuper() #########")
println(super.parentProperty)
super.parentFunction()
}
}
fun main() {
val parentClass = ParentClass()
val childClass = ChildClass()
println("Parent: ${parentClass.parentProperty} / Child: ${childClass.parentProperty}")
parentClass.parentFunction()
childClass.parentFunction()
childClass.useSuper()
}
// 결과
Parent: parentProperty from ParentClass / Child: parentProperty from ChildClass
Hello from ParentClass
Hello from ChildClass
######### useSuper() #########
parentProperty from ParentClass
Hello from ParentClass
4) 상속과 캐스팅
- 자손 객체를 부모 타입에 대입할 경우 스마트 캐스팅이 발생
- 부모 객체를 자손 타입에 대입할 경우 조건에 맞게 명시적 변환이 필요함
- 상속 관계의 객체를 명시적 형변환시 as 키워드를 사용
- null 허용 객체를 대입 시 as? 키워드를 사용
open class ParentCls{}
class ChildCls: ParentCls(){}
fun main() {
val a: ParentCls = ChildCls()
// val b: ChildCls = ParentCls() // 에러!
val b: ChildCls = ParentCls() as ChildCls
val x: ParentCls? = null
val y: ChildCls? = x as? ChildCls
}
5) 접근 제한자
- 클래스, 프로퍼티, 함수 등을 이용할 때 접근 범위를 지정
- 접근 제한자의 종류
public: 어느 곳에서나 접근 가능(기본값)
internal: 같은 모듈 내에서만 접근 가능
protected: 최상위 레벨에서는 사용 불가(클래스 내부에 선언시 해당 클래스 + 서브 클래스에서만 접근 가능)
private: 같은 파일 내에서만 접근 가능 (클래스 내부에 선언시 해당 클래스에서만 접근 가능)
- open과 private는 함께 사용 불가하며 오버라이딩시 접근 범위를 줄일 수 없다.
- private 키워드를 활용해서 클래스 내의 프로퍼티를 읽기 전용으로 사용 가능
class PrivateEx{
private var data: Int = 3
fun getData() = data
}
fun main() {
val pe = PrivateEx()
// pe.data = 5 // 에러!
println(pe.getData()) // 결과 3
}
'프로그래밍 > Kotlin' 카테고리의 다른 글
[Kotlin 요약 정리] 9. 코틀린의 클래스 (0) | 2019.04.10 |
---|---|
[Kotlin 요약 정리] 8. 추상 클래스와 인터페이스 (0) | 2019.04.10 |
[Kotlin 요약 정리] 6. 프로퍼티 (0) | 2019.04.09 |
[Kotlin 요약 정리] 5. 클래스 (0) | 2019.04.08 |
[Kotlin 요약 정리] 4. 흐름 제어 구문과 연산자 (0) | 2019.04.08 |