[Kotlin] 인터페이스
28 Aug 2019 | Kotlin인터페이스(Interfaces)
이 글은 코틀린 공식문서를 공부하며 번역한 글입니다. 틀린 부분이나 어색한 부분을 댓글로 알려주시면 감사하겠습니다.
코틀린 인터페이스에서는 추상메소드와 구현이 있는 메소드 모두 선언할 수 있습니다. 인터페이스와 추상클래스와 다른 점은 인터페이스는 상태(필드)를 저장할 수 없다
는 것입니다. 인터페이스는 추상적이거나 accessor implementations를 제공하는 프로퍼티만을 가질 수 있습니다.
interface MyInterface{
fun bar()
fun foo(){
// optional body
}
}
인터페이스 구현하기(Implementing Interfaces)
인터페이스를 사용하는 방법은 자바보다 간편합니다. 자바에서는 [class] implements [interface]
의 형식으로 구현했지만 코틀린에서는 아래와 같이 클래스 이름 뒤에 콜론(:)을 붙인 뒤 인터페이스 이름을 적으면 됩니다.
class Child : MyInterface{
override fun foo(){
// body
}
}
인터페이스의 프로퍼티(Properties in Interfaces)
인터페이스에서 프로퍼티를 사용할 수 있습니다. 인터페이스에서 선언된 프로퍼티는 추상 프로퍼티이거나 접근자로 구현할 수 있어야 합니다. 인터페이스에 선언된 프로퍼티는 backing fields를 가질 수 없으므로 접근자가 참조할 수 없습니다.
interface MyInterface{
val prop: Int // abstract
val propertyWithImplementation: String
get() = "foo"
fun foo() {
print(prop)
}
}
class Child : MyInterface{
// 코틀린에서는 override 변경자를 꼭 사용해야합니다.
override val prop: Int = 29
}
인터페이스 상속(Interface Inheritance)
인터페이스는 다른 인터페이스에서 상속받을 수 있으며, 상속 받은 인터페이스에서 멤버 구현과 새로운 함수 및 프로퍼티 선언을 할 수 있습니다. 당연히 인터페이스를 구현한 클래스에서는 구현되지 않은 부분만 구현하면 됩니다.
interface Named {
val name: String
}
interface Person : Named {
val firstName: String
val lastName: String
override val name: String get() = "$firstName $lastName"
}
data class Employee(
// implementing 'name' is not required
override val firstName: String,
override val lastName: String,
val position: Position
) : Person
오버라이딩 충돌 해결하기(Resolving overriding conflicts)
상위 타입(supertype)을 많이 선언하면 같은 메소드를 한 번 이상 상속 받는 것처럼 보입니다.
interface A {
fun foo() { print("A")}
fun bar()
}
interface B {
fun foo() { print("B")}
fun bar() { print("bar")}
}
class C : A {
override fun bar() { print("bar")}
}
class D : A, B {
override fun foo() {
super<A>.foo()
super<B>.foo()
}
override fun bar() {
super<B>.bar()
}
}
인터페이스 A와 B 모두 foo()와 bar() 메소드를 선언하고 있습니다. foo() 함수는 A와 B 인터페이스 모두 구현하고 있지만 bar() 함수는 B 인터페이스에서만 구현하고 있습니다( bar() 함수가 인터페이스 A에서 추상메소드로 선언되어 있지 않은 이유는, 함수의 바디가 없다면 이것이 인터페이스의 기본 형태이기 때문입니다). 만약 C 클래스에서 A 인터페이스를 구현한다면, bar() 메소드를 오버라이드하여 구현해야만 합니다.
하지만 만약 D 클래스에서 A와 B 인터페이스를 구현한다면 A와 B 인터페이스에 있는 모든 메소드를 구현해야만 합니다. 또한 D 클래스가 함수들을 어떻게 구현할 것인지 구체적으로 작성해야 합니다. 이 규칙은 단일 구현(single implementation)을 한 bar() 메소드와 다중 구현(multiple implementations)을 한 foo() 메소드 모두에 적용됩니다.
Comments