[Kotlin] Interface

Subeen·2023년 11월 29일
0

Kotlin 문법

목록 보기
8/23

Interface란?

  • 서로 관련성 없는 클래스들이 인터페이스를 구현하게 되는 경우에 사용한다.
  • 인터페이스는 다중 구현을 허용 하고 싶은 경우 사용한다.
  • 인터페이스는 구성 요소들이 자주 바뀔 때 사용하면 유용하며 공통된 메소드(객체 행위)로 만들어 사용하고 싶을 때 인터페이스를 이용하면 효과적이다.
  • 인터페이스는 그 자체의 객체를 생성할 수 없다.
  • 인터페이스의 접근 제어자는 public, open이다.

Interface 정의

  • 자바는 implements를 통해 인터페이스를 구현하지만 코틀린은 콜론(:)을 사용하여 구현한다.
  • 인터페이스 안에는 프로퍼티를 포함할 수 있는데 인터페이스 자체에서 초기화 해줄 수 없으므로 구현체에서 반드시 재정의 해야 한다.
  • 멤버 함수의 경우 선언만 되어 있다면 반드시 재정의 하여 구현 해줘야 한다.
interface MyInterface {
    fun foo()
}

class Child: MyInterface {
    override fun foo() {
        // body
    }
}
  • 인터페이스는 구현 부분을 가질 수 있는데 자체 구현 할 경우 해당 구현이 디폴트로 적용 된다.
interface Clickable {
    var isClicked: Boolean // 추상 프로퍼티
    val message: String
        get() = "status has changed!"  // val로 선언할 경우 게터의 구현이 가능하다.
    fun click()  // 추상 메소드
    // 하위 클래스에서 선택적으로 override 할 수 있다.
    fun showOff() = println("I'm clickable!")  
}

Interface 상속

  • 인터페이스도 다른 인터페이스를 상속 받을 수 있으며 상속 받은 인터페이스에서 멤버 구현과 함수 및 프로퍼티를 선언 할 수 있다.
interface Named {
    val name: String
}

interface Person : Named {
    val firstName: String
    val lastName: String

    override val name: String get() = "$firstName $lastName"
}

Interface vs Abstract

  • 인터페이스와 추상 클래스 둘 다 그 자체의 객체를 생성할 수 없다.
  • 인터페이스는 생성자를 가질 수 없지만 추상 클래스는 생성자를 가질 수 있다.
  • 인터페이스는 다중 구현이 가능하지만 추상 클래스는 상속을 통해 구현이 가능하기에 다중 상속이 불가능하다.
  • 인터페이스는 구성 요소들이 자주 바뀔 때 사용하면 유용하며 서로 관련성 없는 클래스들이 인터페이스를 구현하는 경우 사용한다.
  • 추상 클래스는 추상적인 상위 개념으로 공통 된 개념을 표현할 때 사용하며 추상 클래스를 상속 받은 클래스들이 공통으로 가지는 메소드와 필드가 많은 경우 사용한다.

Bird 클래스를 상속 받을 경우 추상 메소드인 eat(), move(), fly()를 강제적으로 구체화 해야 된다.
예시인 타조와 독수리는 조류이기에 조류를 특징하는 Bird 클래스를 상속받아 사용하려 하지만 타조의 경우 날지 못하기에 fly() 메소드를 사용하는건 부적절하다.

abstract class Animal {  // 동물
    abstract fun eat()
    abstract fun move()
}

abstract class Bird : Animal() {  // 조류
    abstract fun fly()  // 조류의 특성 중 하나인 날기 속성을 추가
}

class Ostrich: Bird() {  // 타조 클래스
    override fun fly() {
        // 타조는 조류지만 날지 못 하기에 해당 메소드를 사용하는 건 부적절하다.
        // Bird 클래스를 상속했기에 하위 클래스에서 강제적으로 구체화 해야 된다.
        println("타조가 날아 갑니다.")
    }

    override fun eat() {
        println("타조가 먹이를 먹습니다.")
    }

    override fun move() {
        println("타조가 움직입니다.")
    }
}

class Eagle: Bird() {  // 독수리 클래스
    override fun fly() {
        println("독수리가 날아 갑니다.")
    }

    override fun eat() {
        println("독수리가 먹이를 먹습니다.")
    }

    override fun move() {
        println("독수리가 움직입니다.")
    }
}

추상 클래스는 한 개의 클래스만 상속이 가능하므로 공통적인 특성을 가진 Animal을 추상 클래스로 선언 하고 선택적으로 특성을 가지기 위해 Bird는 인터페이스로 선언한다.
날지 못하는 타조 클래스는 Bird 인터페이스를 상속 받지 않고 Animal 추상 클래스만 상속 받으며 독수리 클래스의 경우 날 수 있기에 Animal, Bird 둘 다 상속 받아 사용한다.

abstract class Animal {  // 동물
    abstract fun eat()
    abstract fun move()
}

interface Bird {  // 조류
    abstract fun fly()  // 조류의 특성 중 하나인 날기 속성을 추가
}

class Ostrich: Animal() {  // 타조 클래스
    override fun eat() {
        println("타조가 먹이를 먹습니다.")
    }

    override fun move() {
        println("타조가 움직입니다.")
    }
}

class Eagle:Animal(), Bird {  // 독수리 클래스
    override fun fly() {
        println("독수리가 날아 갑니다.")
    }

    override fun eat() {
        println("독수리가 먹이를 먹습니다.")
    }

    override fun move() {
        println("독수리가 움직입니다.")
    }
}

참조
Interface VS Abstract

profile
개발 공부 기록 🌱

0개의 댓글