상속 시에는 기본적으로 수퍼 클래스에서 같은 이름과 형태를 가진 함수는 서브 클래스에서 만들 수 없다.
그러나 수퍼 클래스에서 허용한다면(open 키워드를 사용), 오버라이딩을 통해 서브 클래스에서 같은 이름과 형태로 된 함수의 내용을 구현 가능하다.
fun main(){
var t = Tiger()
t.eat()
}
open class Animal{
open fun eat(){ //open 키워드를 사용하여 Tiger 클래스에서 재구현을 허용한다
println("음식을 먹습니다.")
}
}
class Tiger : Animal(){
override fun eat(){ //오버라이딩으로 재구현
println("고기를 먹습니다.")
}
} //고기를 먹습니다.
오버라이딩과 다르게 추상화는
수퍼클래스에서는 함수의 구체적인 구현은 없고 단지 Animal의 모든 서브 클래스는 eat이라는 함수가 반드시 있어야 한다는 점만 명시하여 각 서브클래스가 비어 있는 함수의 내용을 필요에 따라 구현하도록 하기 위해 사용한다.
fun main(){
var r = Rabbit()
r.eat()
r.sniff()
}
abstract class Animal{ //추상 클래스는 일부 함수가 구현되지 않은 미완성 클래스이므로 단독으로는 인스턴스를 만들 수 없다.
abstract fun eat()
fun sniff(){
println("킁킁")
}
}//따라서 반드시 서브 클래스가 상속을 받아 abstract표시가 된 함수들을 구현해주어야 함
class Rabbit : Animal(){
override fun eat(){
println("당근을 먹습니다.")
}
}
Interface
코틀린에서 Interface는
를 가질 수 있다. 그러나 추상함수는 생성자를 가질 수 있지만, 인터페이스는 생성자를 가질 수 없다.
인터페이스에서
구현부가 있는 함수 → open 함수로 간주
구현부가 없는 함수 → abstract 로 간주
별도의 키워드가 없어도 서브클래서에서 구현 및 재정의가 가능하다.
한번에 여러 인터페이스를 상속 받을 수 있다.
fun main() {
var d = Dog()
d.run()
d.eat()
}
interface Runner{
fun run()
}
interface Eater {
fun eat(){
println("음식을 먹습니다.")
}
}
class Dog : Runner, Eater { //인터페이스 두 개 상속 받음
override fun run(){
println("우다다ㅏ다")
}
override fun eat(){
println("왁념냠")
}
}
여러 개의 인터페이스나 클래스에서 같은 이름과 형태를 가진 함수를 구현 시 서브클래스에서는 혼선이 없도록 오버라이딩하여 재 구현해주어야 한다.
참고자료
디모의 코틀린 강좌