코틀린의 모든 클래스에는 공통의 superclass인 Any 가 있으며, 이는 수퍼타입이 선언되지 않은 클래스의 기본 superclass이다. 기본적으로 코틀린의 클래스와 메소드는 기본적으로 final 이여서 상속이 불가능하다. 클래스를 상속 가능하게 하려면 open 키워드를 사용해야 한다.
상속을 함으로써 아래와 같은 효과(?)를 얻을 수 있다.
- 이미 존재하는 클래스를 확장하여 새로운 속성이나 함수를 확장할때
- 여러 클래스들의 공통점들을 뽑아서 코드관리를 편하게 하고자 할때
open class Base(p: Int)
class Derived(p: Int) : Base(p)
위 코드처럼 서브 클래스에 주 생성자(Primary Constructor)가 있는 경우 주 생성자의 매개 변수를 사용하여 수퍼 클래스를 바로 초기화할 수 있고, 반드시 초기화해야 한다.
또한 클래스 상속에는 여러 규칙들이 있다.
- 서브클래스는 수퍼 클래스에 존재하는 속성과 '같은 이름' 의 속성을 가질 수 없다.
- 서브클래스가 생성 될때는 반드시 수퍼클래스의 생성자까지 호출 되어야 함.
- 기본적으로 수퍼클래스에 있는 함수와 같은 이름과 형태를 가진 함수는 서브클래스에서 사용 불가. 하지만 수퍼클래스에서 open만 한다면 여러개의 서브클래스에서 override를 통해서 사용 가능!!
아래의 예시 코드를 살펴보자.
fun main() {
var a = Animal("숭이", 14, "강아지")
var b = Dog("초코", 16,100)
var c = Cat("냥냥", 12)
a.introduce()
b.introduce()
b.bark()
c.introduce()
c.meow()
}
open class Animal (var name: String, var age: Int, var type: String) {
fun introduce() {
println("안녕 나는 ${type}인 ${name}이고 ${age}살이야")
}
}
class Dog (name: String, age: Int, var height: Int) : Animal(name, age, "강아지") {
fun bark() {
println("멍멍")
println("내 키는 ${height}")
}
}
class Cat (name: String, age: Int) : Animal(name, age, "고양이") {
fun meow() {
println("야옹야옹")
}
}
특이한 점은 Dog 클래스 생성자의 var height : Int <--이 부분이다. 수퍼 클래스에는 없는 독자적인 속성을 가진다. 겹치는 속성이 수퍼 클래스에 없으므로 사용 가능하다. 그리고 서브 클래스를 생성할 때에는 반드시 수퍼클래스의 생성자를 호출 해 줘야한다. 매우매우 중요하다!!
다음으로는 수퍼 클래스의 메소드와 같은 이름의 메소드를 서브 클래스에서 그 기능을 변경해서 사용하는 방법을 알아보자. override 키워드를 사용한다. 오버라이딩은 이미 수퍼 클래스에서 구현이 끝난 함수의 기능을 서브 클래스에서 변경하고자 할때 사용한다.
fun main() {
var t = Tiger()
t.eat()
}
open class Animal {
open fun eat() {
println("음식을 먹습니다")
}
}
class Tiger : Animal() {
override fun eat() {
super.eat()
println("고기를 먹습니다")
}
}
수퍼 클래스인 Animal 에서 이미 정의된 eat 메소드를 서브 클래스인 Tiger 에서 override를 통해서 변경하였다. Tiger 클래스의 인스턴스인 t에서 t.eat() 을 통해서 eat 메소드를 호출하면 override된 서브 클래스의 메소드가 호출된다. 부모 클래스의 메소드를 호출하고자 할 때에는 super.eat() 을 사용한다.
override 키워드가 붙은 메소드는 open 함수로 간주되므로 서브 클래스에서 override 할 수 있다. 만약 re-override를 금지하고 싶다면 final 키워드를 붙이면 된다. 아래 예시 코드와 같다.
open class Rectangle() : Shape() {
final override fun draw() { /*...*/ }
}
여기서 오해하기 쉬운 점이 있다. draw 함수에 final 키워드가 붙었다고 해서 더 이상 모든 클래스에서 draw 함수를 override 하지 못한다는 것은 아니다. 가령 Shape 클래스의 서브 클래스에 Rectangle 말고도 Triangle이 있다고 한다면, Triangle 함수에서는 draw 함수를 override 할 수 있다.
Rectangle 클래스 내부의 draw 함수에 final 키워드가 붙음으로써 Rectangle 클래스를 수퍼 클래스로 가지는 서브 클래스에서 draw 함수를 re-override 하지 못하게 된다.
'안드로이드 > [Kotlin]' 카테고리의 다른 글
[Kotlin] 상단의 Status Bar를 투명하게 만들어 보자. (0) | 2021.10.04 |
---|---|
[Kotlin] ListView 생성. Custom Adapter 사용하기 (0) | 2021.08.20 |
[Kotlin] Activity 전환 & 데이터 전달 (Intent, putExtra...) (0) | 2021.08.07 |
[Kotlin] View Binding (뷰 바인딩) (0) | 2021.08.06 |
[Kotlin] 클래스와 생성자(constructor) (0) | 2021.05.08 |