Kotlin에서 super 키워드는 슈퍼 클래스 또는 구현된 인터페이스의 메소드 또는 속성 구현에 접근하는 데 사용됩니다. Java와 달리, Kotlin은 어떤 인터페이스 또는 클래스를 통해 메소드 구현을 호출할지를 명시적으로 지정할 수 있으므로, 동일한 메소드를 가진 여러 인터페이스 간의 '충돌'이 중요하게 됩니다.
특징: 클래스가 동일한 시그니처를 가진 메소드를 정의하는 여러 인터페이스를 구현하고 기본 구현이 있을 경우, 어떤 구현을 사용할지를 명시적으로 지정해야 합니다.
예시:
interface A { fun foo() = println("A") } interface B { fun foo() = println("B") } class C : A, B { override fun foo() { super<A>.foo() // 명시적으로 A.foo를 호출 super<B>.foo() // 명시적으로 B.foo를 호출 } }
이것은 Java에서 직접 지원되지 않습니다(Java는 인터페이스가 메소드 구현을 가질 수 없도록 허용하지 않으며, Java 8에서도 메커니즘이 다릅니다).
"Kotlin에서 상속의 여러 수준을 통해 슈퍼 클래스의 메소드 구현에 접근할 수 있습니까?"
super<Intermediate>.foo()를 통해 구현에 접근할 수 있다고 생각하지만, 이는 사실이 아닙니다 — 직접적인 슈퍼 클래스나 이 메소드를 직접 구현하는 인터페이스에만 접근할 수 있습니다.예시:
open class Base { open fun foo() = println("Base") } open class Mid : Base() { override fun foo() { println("Mid"); super.foo() } } class Child: Mid() { override fun foo() { super.foo() // Mid.foo()를 호출 // super<Base>.foo() — 컴파일 오류 } }
이야기
큰 프로젝트에서 인터페이스
Logger와Auditor는 모두 메소드record()를 정의했습니다. 두 인터페이스를 모두 상속하는 클래스를 구현할 때, 프로그래머가 명시적으로record()를 재정의하지 않았습니다. 그 결과 "Class must override public open fun record()"라는 컴파일 오류가 발생했습니다. 메소드를 수동으로 구현하고 해당 인터페이스로 명시적으로 위임해야 했습니다.
이야기
여러 중간 레이어를 통해 슈퍼 클래스의 구현된 메소드를 호출하려 할 때(
super<Base>.foo()등), 컴파일 오류가 발생했습니다. 개발자는 Kotlin의 제한을 알지 못해 왜 직접 호출이 불가능한지 이해할 수 없었습니다.
이야기
API가 업데이트된 후, 한 인터페이스가 다른 인터페이스와 일치하는 기본 함수 구현을 추가했습니다. 이전 코드는 구현 충돌로 인해 더 이상 컴파일되지 않았습니다 — 충돌을 명시적으로 해결하고, 자신의 내부에서 어떤 슈퍼 인터페이스의 구현을 호출할 것인지를 선택해야 했습니다.