TIL

Lec 10. 코틀린에서 상속을 다루는 법

1. 추상 클래스

abstract class Animal(
  protected val species: String, // 무슨 종인지
  protected open val legCount: Int // 다리 개수, Penguin에서 오버라이드가 필요해 open 추가
) {

  abstract fun move()
}

class Cat(
  species: String
) : Animal(species, 4) { // 고양이 다리는 4개

  override fun move() {
    println("고양이가 사뿐 사뿐 걸어가~")
  }
}

class Penguin(
  species: String
) : Animal(species, 2) { // 펭귄 다리는 2개

  private val wingCount: Int = 2 // 펭귄 날개는 2개
  
  override fun move() {
    println("팽귄이 움직인다.")
  }
  
  override val legCount: Int // legCount 프로퍼티를 오버라이드
      get() = super.legCount + this.wingCount
}

코틀린 상속의 특징

2. 인터페이스

interface Flyable {
  fun act() {
    println("파닥 파닥")
  }
}

interface Swimmable {
  fun act() {
    println("어푸 어푸")
  }
}

코틀린 인터페이스 특징

class Penguin(
  species: String
) : Animal(species, 2), Swimable, Flyable { 

  private val wingCount: Int = 2
  
  override fun move() {
    println("팽귄이 움직인다.")
  }
  
  override val legCount: Int
      get() = super.legCount + this.wingCount
      
  override fun() {
    super<Swimable>.act()
    super<Flyable>.act()
  }
}

코틀린 인터페이스 구현 특징

interface Swimmable {

  val swimAbility: Int // backing field 없는 프로퍼티

  fun act() {
    println("어푸 어푸")
  }
}

class Penguin(
  species: String
) : Animal(species, 2), Swimable, Flyable { 
  // ...
  override val swimAbility: Int // 구현체에서 오버라이드 가능
      get() = 3
}

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

open class Base( // 상속이 가능하도록 open
  open val number: Int = 100 // 오버라이드 가능하도록 open
) {
  init {
    println("Base Class")
    println(number)
  }
}

class Derived(
  override val number: Int // number 프로퍼티 오버라이드
) : Base(number) {
  init {
    println("Derived Class")
  }
}

fun main() {
  Derived(300)
  
  // 출력 결과
  // Base Class
  // 0
  // Derived Class
}
public final class Derived extends Base {
   private final int number;

   public Derived(int number) {
      super(number); // 1. 상위 클래스 생성자 호출, number 초기화 안 됨
      this.number = number; // 4. number 초기화
      // ...
   }
} 

public class Base {
   private final int number;

   public Base(int number) {
      this.number = number; // 2. 초기화되지 않은 number 전달 받음
      // ...
      System.out.println(var3); // 3. 초기화되지 않은 number 출력 -> 0
   }
   // ...
}

4. 상속 관련 지시어 정리

  1. final: override를 할 수 없게 한다. 기본적으로 보이지 않게 존재
  2. open: override를 열어 준다.
  3. abstract: 반드시 override 해야 한다.
  4. override: 상위 타입을 오버라이드하고 있다.