10. 오버라이딩과 추상화

Yes. Dominos~·2021년 9월 7일
0

디모의 코틀린

목록 보기
10/10
post-thumbnail

이글은 유튜브 강좌 <디모의 코틀린> 강좌를 보고 요약작성한 글 입니다.
https://www.youtube.com/playlist?list=PLQdnHjXZyYadiw5aV3p6DwUdXV2bZuhlN
강좌를 보고 싶은 분은 위 링크를 통해 공부하실수 있습니다.

오버라이딩(overriding)

overriding은 부모 클래스에서 이미 만들어진 함수(fun)를,
자식 클래스에서 재정의 할 수 있게끔 한다. (수퍼(부모)클래스가 허용 하에 가능)

코드를 보면서 이해하자.

fun main() {
    val t = Tiger()
    t.eat()
}

open class Animal {
    fun eat() {
        println("음식을 먹습니다.")
    }    
}

class Tiger : Animal()

결과값 :
음식을 먹습니다.

Tiger 클래스에서 eat() 함수를 재정의 하고 싶은데, 이미 수퍼(부모)클래스에서 정해져 버림.
하지만!
open을 이용하여 부모클래스 fun 함수를,
자식클래스에서 overriding 할수 있게끔 하면?

fun main() {
    val t = Tiger()
    t.eat()
}

open class Animal {
    open fun eat() {
        println("음식을 먹습니다.")
    }    
}

class Tiger : Animal(){
    override fun eat(){
        println("고기를 먹습니다.")
    }
}

결과값 :
고기를 먹습니다.

  • 요약 : 부모에서 함수 open 허용 후, 자식에서 overriding 를 사용하여 재정의.



추상화(Abstract)

위의 오버라이딩의 경우, 부모에서 A함수를 만들고 함수 내용을 구성하였으나,
자식이 필요에 따라 A함수를 재정의를 하는 경우 이다.

이번의 경우, 부모는 A함수를 만들긴 하는데 안에 내용은 비어 있고(속은 비어있고 껍데기만 있음),
"자식은 꼭 A함수를 가지고 있어야 한다"라는 점만 부모에서 명시할때,
각 서브클래스가 비어있는 함수의 내용을 필요에 따라 구현하는 것을 추상화 라고 한다.

코드를 보면서 이해하도록 합시다.

fun main() {
    var r = Rabbit()
    r.eat()
    r.sniff()
}

// 추상 클래스
abstract class Animal {
    
    // 추상 함수
    abstract fun eat() 
    
    // 일반 함수
    fun sniff() {
        println("킁킁")
    }
}

// Animal 추상클래스를 상속받은 Rabbit 클래스
class Rabbit : Animal() {
    // 추상함수 eat()를 정의
    override fun eat(){
        println("당근을 먹습니다.")
    }
}

결과값 :
당근을 먹습니다.
킁킁

이렇게 abstract를 붙인 추상클래스는 미완성이기때문에 단독으로 인스턴스를 만들수는 없다.
따라서 서브 클래스에서 상속받아서 구현을 완성해야한다.




인터페이스(Interface)

위의 경우, 추상화를 위해 abstract class 를 이용하였는데,
Interface 를 이용하는 방법도 있다.

코틀린에서 인터페이스는

• 속성
• 추상함수
• 일반함수
모두를 가질 수 있다.

다만 추상함수는 생성자를 가질 수 있는 반면,
인터페이스는 생성자를 가질수 없다.

또한, 인터페이스에서 '함수의 내부 구현 여부' 에 따라 달라지는 것이 있는데,

마지막으로, 한번의 여러 인터페이스를 상속받을 수 있으므로 좀 더 유연한 설계가 가능.

코드를 보면서 이해하도록 합시다.

fun main() {
    var d = Dog()
    d.run()
    d.eat()
}

// Runner 인터페이스
interface Runner{
    // 추상함수
    fun run()
}
// Eater 인터페이스
interface Eater{
    // 일반함수
    fun eat() {
        println("음식을 먹습니다.")
    }
}

// 인터페이스 2개를 상속받은 Dog 클래스
class Dog : Runner, Eater {
    // 추상함수 재정의
    override fun run(){
        println("우다다다 뜁니다.")
    }
    // 일반함수 재정의
    override fun eat(){
        println("허겁지겁 먹습니다.")
    }
}

결과값 :
우다다다 뜁니다.
허겁지겁 먹습니다.

요약하여 정리하면,
1. 오버라이딩 : 이미 구현이 끝난 부모의 함수를, 자식이 재정의 할때 사용.
2. 추상클래스 : 부모에서 내용이 비어 있는 함수를, 이를 자식이 정의해서 사용.
3. 인터페이스 : 서로 다른 기능들을 여러개 물려줘야 할때 유용하게 사용.

profile
미래의 아들아~ 곧 만나러 갈게

0개의 댓글

관련 채용 정보