본문 바로가기

코틀린에서의 OOP - 2. 상속

@silver-w2025. 10. 6. 19:58

□ 상속


  1. 추상 클래스
  2. 인터페이스
  3. 클래스를 상속할 때 주의할 점
  4. 상속 관련 지시어 정리
 - extends와 implements 는 : (콜론)으로 사용한다
 - 상위 클래스 상속을 구현할 때 반드시 생성자 호출
 - override는 애노테이션으로 사용하지 않는다
 - abstract 또는 open 키워드를 붙여야 override가 가능하다 (default = final)
 - "상위 클래스"의 생성자/init 블록에는 open 프로퍼티를 사용하면 안된다(예기치못한 버그 발생)

더보기

1 .  추상 클래스

(1) Animal.kt

abstract class Animal (
    protected val species: String,
    protected open val legCount: Int
) {
    abstract fun move()
}

 - open : 클래스와 프로퍼티는 기본적으로 final 이다, 이에 open 키워드를 해야 자식 클래스에서 override가 가능하다.
 - 다만, 추상 프로퍼티 (abstract val ....)은 자식 클래스가 반드시 override를 해야하기 때문에 자동으로 open이다.

 

(2) Cat.kt

class Cat(
    species: String,    
) : Animal(species, 4) {   
    override fun move() {
        println("mya")
    }
}

- extends 는 콜론(:)으로 대체한다, Body 전에 『space + : + 부모클래스 생성자』 를 입력한다.
- : Animal(species, 4) 는 자바에서 extends Animal + super(species, 4) 와 동일하다.

- 메서드 오버라이드는 fun 앞에 override를 붙인다.

 

(3) Penguin.kt

class Penguin (
    species : String
) : Animal(species, 2) {
    private val wingCount: Int = 2

    override fun move() {
        print("kk")
    }

    override val legCount: Int      
        get() = this.wingCount + super.legCount
}

- 추상(부모)클래스에서 자동으로 만들어진 getter를 override하려면 커스텀 getter를 이요하면 된다. 

- 이때, 부모 클래스에서 해당 프로퍼티를 abstract로 선언하지 않았다면 open을 붙여줘야한다.


2 . 인터페이스

- 예제 구현 구조

Penguin
▲ Implement
Flyable Animal Swimmable

 

interface Flyable interface Swimable abstract class Animal

- Penguin.kt

class Penguin (
    species : String
) : Animal(species, 2), Swimable, Flyable { 
    private val wingCount: Int = 2

    override fun move() {
        print("kk")
    }

    override val legCount: Int
        get() = this.wingCount + super.legCount

    override fun act() {    
        super<Flyable>.act()
        super<Swimable>.act()
    }

    override fun fly() {
        println("fly")
    }

}

 → extends 방식과, implements 방식이 동일하다.
 → 중복되는 인터페이스를 특정할 때 super<타입>.함수 를 사용한다

 

※ 자바에선?

public final class Penguin extends Animal implements Flyable, Swimable {
    
    @Override
    public void act() {
        Swimable.super.act();
        Flyable.super.act();
    }
}

 

+ Kotlin에서는 backing field가 없는 프로퍼티를 interface에 만들 수 있다.

 - 구현 클래스에서 해당 field 구현을 기대하며 프로퍼티를 interface에 선언할 수 있다

 - 이때 interface에 디폴트 값을 설정해 두어도 되고, (이경우 자식 클래스에서 해당 프로퍼티를 구현을 하지 않더라도 컴파일 에러가 나지 않는다) 설정하지 않아도 된다.


interface Swimable {
    val swimAbility: Boolean

    val hasDefaultAbility: Int
        get() = 0	// 인터페이스에서 디폴트 값 설정이 가능하다.

    fun act() {
        println(swimAbility)	// 구현 클래스에서 구현해줄거라 해당 backing field없는 프로퍼티를 호출할 수 있는 것
    }
}

class Penguin(
	....
) : Swimmable {
	....
    
    override val swimAbility: Boolean
        get() = false
    
//    override val hasDefaultAbility: Int
//        get() = super.hasDefaultAbility
}

▶ swimAbility는 기본값이 없으므로 penguin 클래스에서 구현해야 컴파일 에러가 나지 않는다

     hasDefaultAbility는 기본값이 있으므로 penguin 클래스에서 디폴트로 구현을 하지 않아도 컴파일 에러가 나지 않는다.


 

3 . 클래스를 상속할 때 주의할 점

package extend

open class Base(
    open val number: Int = 100
) {
    init {
        println("Base")
        println(number)
    }
}

class Derived(
    override val number: Int
) : Base(number) {
    init {
        println("Derived")
        println(number)
    }
}

fun main() {
    val derived = Derived(300)
}

※ 실행결과

Base
0
Derived
300

▶ 상위 클래스를 설계할 때 생성자/초기화 블록에 사용되는 프로퍼티에는 open을 피해야 한다.
 

4 . 상속 관련 키워드 4가지

- fianl : 코틀린에서는 디폴트로 작용된다

- open : override를 허용

- abstract : override를 반드시 해야한다.

- override  : 어노테이션이 아니라 키워드로 사용한다.
 

 


 

※ (intellij) 코틀린 코드 자바로 변환
tool > Kotlin > Show Kotlin Bytecode


출처 : https://inf.run/sMPv5

 

자바 개발자를 위한 코틀린 입문(Java to Kotlin Starter Guide)| 최태현 - 인프런 강의

현재 평점 5.0점 수강생 3,549명인 강의를 만나보세요. 이 강의를 통해 Kotlin 언어의 특성과 배경, 문법과 동작 원리, 사용 용례, Java와 Kotlin을 함께 사용할 때에 주의할 점 등을 배울 수 있습니다. Ko

www.inflearn.com

silver-w
@silver-w :: silver-w 님의 블로그

silver-w 님의 블로그 입니다.

공감하셨다면 ❤️ 구독도 환영합니다! 🤗

목차