Image
Kotlin/Design Patterns

[Delegate Pattern] 2. by 키워드를 이용하여 Delegate Pattern 구현하기

목표

  • by 키워드를 이용하여 Delegate Pattern을 구현하는 방법을 안다.

개요

Kotlin에서는 Delegate Pattern을 구현하기 위한 키워드인 by 키워드를 제공한다. 클래스 선언부의 by 키워드를 먼저 살펴보자

 

클래스 선언부의 by 키워드

클래스 선언부에는 interface가 implement되거나 다른 클래스가 상속될 수 있다. 위임 패턴은 인터페이스 구현부를 다른 클래스에 위임하는 것이기 때문에 인터페이스 구현에만 사용될 수 있다. 따라서 Kotlin의 위임패턴을 도와주는 by키워드는 다음과 같은 제한을 가진다.

  • by 키워드는 interface가 implement되는 경우에만 사용될 수 있다.
  • 클래스 상속에는 by 키워드 사용이 불가능하다.
  • 변수(val, var)와 메서드(fun)에 대한 위임만이 가능하다.

자 이제 interface가 implement되는 것을 살펴보자. 먼저 다음과 같이 부동산계약 인터페이스를 구현하는 본인 클래스를 준비한다.

interface 부동산계약 {
    fun 계약하기()
}

class 본인() : 부동산계약 {
    override fun 계약하기() {
        println("집이 계약되었습니다")
    }
}

 

메서드(fun) 위임

본인의 부동산계약 내부의 계약하기 행위를 부동산 중개인 클래스에 위임하고 싶다고 해보자. 다음 코드와 같이 구현할 수 있다.

interface 부동산계약 {
    fun 계약하기()
}

class 본인() : 부동산계약 {
    override fun 계약하기() {
        println("집이 계약되었습니다")
    }
}

val me = 본인()

class 부동산중개인() : 부동산계약 by me

부동산 중개인은 본인의 계약하기 동작(fun)을 위임받는다.

 

프로퍼티 위임

프로퍼티 또한 다음 코드와 같이위임될 수 있다.

interface 부동산계약 {
    val 계약자이름 : String
    fun 계약하기()
}

class 본인(val 이름 : String) : 부동산계약 {
    override val 계약자이름 = 이름
    override fun 계약하기() {
        println("${계약자이름} 집이 계약되었습니다")
    }
}

val me = 본인("dev_cho")

class 부동산중개인() : 부동산계약 by me

fun main() {
    부동산중개인().계약하기() // dev_cho 집이 계약되었습니다.
}

이렇게 되면 본인("dev_cho")의 집 계약 행위를 부동산중개인이 위임받아 계약하기를 할 수 있게 된다.

 

입력 받은 변수로 부터 위임 받기

위의 예시와 같이 외부의 me 변수를 쓰지 않고 다음과 같이 입력 받은 변수로부터 위임을 받을 수도 있다. 

class 부동산중개인(위임인 : 부동산계약) : 부동산계약 by 위임인

입력 받은 변수로 부터 위임 받는 방식으로 코드를 짜게 되면 코드 유연성이 올라가게 된다. 따라서 이미 선언된 변수로부터 위임 받는 방식보다는 입력 받은 변수로 부터 위임 받는 방식으로 위임을 사용하는 것이 좋다.

 


변수에서의 by 키워드

위에서는 클래스 선언부의 by 키워드를 보았다. 이제는 변수 선언부의 by 키워드를 살펴보도록 하자. 

 

인스턴스가 변수에 위임

interface 부동산계약 {
    val 계약자이름: String
    fun 계약하기()
}

class 본인(val 이름: String) : 부동산계약 {
    override val 계약자이름 = 이름
    override fun 계약하기() {
        println("${계약자이름} 집이 계약되었습니다")
    }

    operator fun getValue(nothing: Nothing?, property: KProperty<*>): 부동산계약 {
        return 본인(이름)
    }
}

val 부동산중개인: 부동산계약 by 본인("dev_cho")

변수인터페이스를 구현하는 변수가 객체로부터 생성된 생성된 인스턴스로부터 위임을 받을 때는 operator fun getValue 가 호출된다. 따라서 operator fun getValue를 구현해야만 객체의 인스턴스가 인터페이스를 구현하는 변수에 위임을 할 수 있게 된다.

 


정리

위임 패턴을 사용해 보일러 플레이트 코드를 줄이고, 코드의 유연성을 높이는 작업을 할 수 있다. by 키워드를 이용해 위임 패턴을 구현해보도록 하자.

 

반응형

 

이 글의 저작권은 '조세영의 Kotlin World' 에 있습니다. 글, 이미지 무단 재배포 및 변경을 금지합니다.

 

 

Kotlin, Android, Spring 사용자 오픈 카톡

오셔서 궁금한 점을 질문해보세요!
비밀번호 : kotlin22

open.kakao.com