본문 바로가기
Language/Kotlin

[Kotlin IN ACTION] - Kotlin Interface(인터페이스)

by Jman 2022. 7. 22.

코틀린 인터페이스

코틀린 인터페이스는 자바 8 인터페이스와 비슷하다.

코틀린 인터페이스는 안에는 추상 메서드뿐 아니라 구현이 있는 메서드도 정의할 수 있다.

다만, 인터페이스에는 아무런 상태(field)도 들어갈 수 없다.

// click 이라는 추상 메서드가 있는 인터페이스 정의
interface Clickable {
	fun click()
}

이 인터페이스를 구현하는 모든 비추상 클래스(또는 구체적 클래스)는 click 에 대한 구현을 제공해야 한다.

 

// 인터페이스 file
interface Clickable {
    fun click()
}

// 구체적 클래스 file
class Button : Clickable {
    override fun click() = println("I was clicked")
}

fun main() {
    Button().click()
}

코틀린에서는 override 변경자를 꼭 사용해야 한다.

override 변경자는 실수로 상위 클래스의 메서드를 오버라이드하는 경우를 방지해준다.

상위 클래스에 있는 메서드와 시그니처가 같은 메서드를 우연히 하위 클래스에 선언하는 경우 컴파일이 안 되기 때문에

override 를 붙이거나 메서드 명을 변경해야 한다.

 

또한, 인터페이스 메서드도 디폴트 구현을 제공한다.

자바와는 다르게 코틀린은 메서드 앞에 default붙일 필요가 없다.

 

interface Clickable {
    fun click()  // 일반 메서드 선언 (구현을 제공해야 한다.)
    fun showOff() = println("I'm clickable!") // 디폴트 구현이 있는 메서드
 }

위와 같이 showOff 메서드를 보면, 새로운 동작을 정의할 수도 있고, 그냥 정의를 생략해서 디폴트 구현을 사용할 수도 있다.

 

한 클래스에서 두 인터페이스를 함께 구현하면 어떻게 될까??

두 인터페이스 모두 디폴트 구현이 들어있는 showOff 메서드가 있다

interface Focusable {
    fun setFocus(b : Boolean) =
        println("I ${if (b) "got" else "lost"} focus.")
    fun showOff() = println("I'm focusable!")
}

 

어느 쪽 showOff 메서드가 선택될까?

정답은 어느 쪽도 선택되지 않는다.

두 상위 인터페이스에 정의된 showOff 구현을 대체할 오버라이딩 메서드를 직접 제공하지 않으면 컴파일 오류가 발생한다.

 

코틀린 컴파일러는 두 메서드를 아우르는 구현을 하위 클래스에 직접 구현하게 강제한다.

class Button : Clickable, Focusable {
    override fun click() = println("I was clicked")

    override fun showOff() {
    // 상위 타입의 이름을 꺾쇠 괄호 사이에 넣으면, 어떤 상위 타입의 멤버 메서드를 호출할지 지정할 수 있다.
        super<Clickable>.showOff()
        super<Focusable>.showOff()
    }
}

fun main() {
    Button().click()
    Button().showOff()
}

이름과 시그니처가 같은 멤버 메서드에 대해 둘 이상의 디폴트 구현이 있는 경우, 인터페이스를 구현하는 하위 클래스에서 명시적으로 새로운 구현을 제공해야 한다.