코틀린 언어 정리 2-5

interface

클래스와 비교

개념적 차이점

  • 클래스의 경우, 상위 클래스 "Super" 와 이를 상속 받은 하위 클래스"Sub" 가 있다고 할 때 Super와 Sub의 구현은 Sub "is a" Super 로 표현 가능해야 합니다.

  • 인터페이스의 경우, 인터페이스 "IFun" 과 이를 상속 받은 클래스 "Sub" 가 있다고 할 때 Sub "has a" IFun 의 개념으로 사용합니다.


추상 클래스와의 동작 비교

비슷한점

  • 인터페이스, 추상 클래스는 그 자체로 객체를 생성할 수 없습니다. 하지만 이를 상속받은 하위 클래스는 추상 클래스와 마찬가지로 인터페이스도 타입처럼 사용할 수 있습니다.

  • 상속 받는 하위 클래스에서 abstract 멤버( 프로퍼티, 함수 )의 구현을 강제합니다.

  • 필요할 경우 구현을 추가하여 기능 상속을 할 수 있습니다.

  • 하위로 멤버의 구현을 미룬다는 목적에서 여러모로 동작이 비슷합니다.


추상 클래스와의 차이점

  • 인터페이스 또는 클래스에서 인터페이스를 다중 상속 하는 것이 가능합니다.

  • 멤버(프로퍼티, 함수)를 추상으로 만들 때 abstract, open 키워드를 추가할 필요가 없습니다.

  • 추상 클래스와는 다르게 멤버 선언 시 구현( 함수 구현, 프로퍼티 초기화 등 )을 추가하지 않으면 기본으로 abstract로 처리 됩니다. abstract는 open을 내재하므로 상속 가능을 명시하기 위해 open 키워드를 추가할 필요도 없습니다.

  • 프로퍼티를 가질 수는 있지만 backing field는 가질 수 없습니다.( get/set 구현에 field를 사용할 수 없습니다. ) 즉 상태(값)를 저장할 수 없으며 고정된 값이나 로직만 추가할 수 있습니다.

  • 생성자가 없습니다.


overriding conflicts 상황에서의 접근 방법

다음은 추상 클래스 1개와 인터페이스 2개를 상속 받은 클래스에서 이름이 겹치는 상위(super)클래스나 인터페이스들의 멤버를 접근( overriding conflicts )하는 방법에 대한 예제입니다.


예제

abstract class AbstractSuper(name: String) {

   open val name: String

   abstract var age: Int

   abstract var company: String


   init {

       this.name = "AbstractSuper::name = " + name

   }


   abstract fun funAbstract()

   open fun funNonAbstract() {

       println("AbstractSuper::funNonAbstract")

   }

}


interface ISuper {

   val name: String

       get() {

           return "ISuper::name = unknown"

       }

   var age: Int

   var company: String

   fun funAbstract()

   fun funNonAbstract() {

       println("ISuper::funNonAbstract")

   }

}


interface ISuper1 {

   val name: String

       get() {

           return "ISuper1::name = unknown1"

       }

   var age: Int

   var company: String

   fun funAbstract()

   fun funNonAbstract() {

       println("ISuper1::funNonAbstract")

   }

}


class SubA(name: String, age: Int, company: String) : AbstractSuper(name), ISuper, ISuper1 {

   override val name: String = "SubA::name = " + name

   override var age: Int = age

   override var company: String = company

   override fun funNonAbstract() {

       super<ISuper>.funNonAbstract()

       super<AbstractSuper>.funNonAbstract()

   }


   override fun funAbstract() {

       println("SubA::funAbstract()")

       println("this SubA.name: ${name}")

       println("super<AbstractSuper>.name: ${super<AbstractSuper>.name}")

       println("super<ISuper>.name: ${super<ISuper>.name}")

       println("super<ISuper1>.name: ${super<ISuper1>.name}")

   }

}


fun test() {

   var obj = SubA("R", 10, "UCompany")

   obj.funNonAbstract()

   obj.funAbstract()

}


+ Recent posts