Inheritance
객체지향적인 언어의 장점 중 하나는 바로 상속이다.
코틀린에서의 상속을 알아보자.
코틀린의 최상의 클래스는 Any이다. 클래스에 상위 타입을 선언하지 않으면 Any가 상속된다.
class Ex1 //암시적 Any상속
class Ex2: Any() //명시적 Any상속
Any는 java에서 Object와 비슷해 보이지만 조금 다르다.
equals(), hashCode(), toString()만 존재한다.
상속을 해줄 클래스가 open을 해줘야 상속이 가능하다. 또한 부모 클래스에 기본 생성자가 있다면 호출하여 초기화 가능하다. 코틀린에서 클래스는 기본적으로 final이다. 따라서 상속을 원한다면 open을 반드시 적어야 한다.
open class parent(firstName: String)
class child: parent("lee")
만약 자식클래스에 기본 생성자가 없으면 각각의 보조 생성자에서 상위 타입의 super 키워드를 이용해서 초기화해줘야 한다.
class MyView: View{
constructor(): super(1)
constructor(ctx: Int): this()
constructor(ctx: Int, attrs: Int): super(ctx, attrs)
}
메서드 오버라이딩
메서드도 오버라이딩하려면 open 어노테이션을 해야 한다.
또한 오버라이딩하는 메서드에서도 override 어노테이션을 해야 한다.
open class Base{
open fun v() {}
fun nv() {}
}
class Derived(): Base() {
override fun v() {}
}
프로퍼티 오버라이딩
메서드 오버라이딩과 동일하다.
open class Base{
open val x: Int get { }
}
class Derived(): Base() {
override val x: Int
}
오버라이딩에는 규칙이 있다.
같은 멤버에 대한 중복된 구현을 상속받은 경우, 상속받은 클래스는 해당 멤버를 오버라이딩하고 자체 구현을 제공해야 한다.
open class A{
open fun f() { print("A") }
fun a() {print("a")}
}
interface B{
fun f() {print("B")}
fun b() {print("b")}
}
class C(): A(), B{
override fun f() {
super<A>.f()
super<B>.f()
}
}
인터페이스와 상속에서 이름이 겹치는 함수가 있다면 모호성이 생긴다.
자바는 인터페이스에서의 구현을 막아 놓았기 때문에 이런 문제가 없지만 코틀린은 조금 다르다.
따라서 코틀린은 이런 문제를 위와 같이 super + <클래스 명>으로 지정함으로써 문제를 해결했다.
추상 클래스
자바와 동일하게 추상 클래스가 존재한다.
abstract 키워드로 만들 수 있다. abstract 멤버는 구현이 없고 open을 적지 않아도 된다.