[Kotlin][Delegation] 1. Class Delegation

Choi Sang Rok·2022년 6월 21일
1

Kotlin

목록 보기
4/6

코틀린에서 많이 사용하는 by 키워드, 특히나 뷰모델을 사용할 때 많이 봤었습니다.
val viewModel: MainViewModel by viewModels()
단순히 viewModel을 위임하는 것이라고 알고 있었는데, 위임한다는 것이 무슨 의미이고, 어떤 식으로 작동하는지 알아보려고 합니다.



🌎Delegate Pattern


소프트웨어 엔지니어링에서 delegate pattern(위임 패턴)
은 객체 합성이 상속과 동일하게 코드 재사용을 할 수 있도록 하는 객체 지향 디자인 패턴이다.
https://en.wikipedia.org/wiki/Delegation_pattern
Delegate Pattern은 디자인 패턴 중 하나로, 한 객체가 다른 객체로부터 기능 일부를 넘겨받아 데이터를 제공하거나 특정 작업을 수행 할 수 있게 하는 것입니다.



🚩In OOP


객체지향에서는 상속을 허용하지 않는 클래스에 새로운 기능을 추가할 때 위임을 사용할 수 있습니다.
위임을 사용하면 상속하지 않고 기존 기능을 그대로 사용하면서 새로운 기능을 추가 할 수 있습니다.



🏬Delegation In Kotlin


Kotlin에서는 Delegate Pattern을 by라는 키워드로 제공하고 있습니다.
by 라는 키워드는 Delegation을 직접 구현하는 데에서 생기는 보일러 플레이트 코드의 감소를 목적으로 사용됩니다.


Class Delegation

interface Champion {
    val hp: Int,
    val mp: Int,
    fun info()
}

League of Legend라는 게임을 예시로 들어서 설명해 보겠습니다.
Champion이라는 인터페이스는 체력과 마나를 뜻하는 hp, mp, 체력과 마나 정보를 출력하는 info() 메서드를 가지고 있습니다.

class User(private val champ: Champion) : Champion {
    override val hp: Int = champ.hp
    override val mp: Int = champ.mp
    override fun info() = champ.info()
}

User라는 클래스는, Champion을 직접 구현하는 것이 아닌, Champion 인터페이스의 구현체를 인자로 받아, 프로퍼티와 메서드를 위임 받고 있습니다

class Ezreal : Champion {
  override val hp: Int = 500
  override val mp: Int = 400

  override fun info() {
print("체력은 $hp, 마나는 $mp 입니다.")
  }
}

fun main(){
  val user = User(Ezreal())
  user.info()
}

자 그러면 이렇게 UserChampion의 구현체인 Ezreal을 전달하면, User 객체는 Ezreal을 상속받지 않더라도 Ezreal의 기능을 사용할 수 있습니다.

하지만, 프로퍼티가 많으면 많아질수록 위임하는 코드는 많아질 것이고, 이는 불필요한 코드를 야기할 것입니다.

이를 위해 코틀린에서 지원하는 키워드가 by 입니다.

class User(private val champ: Champion) : Champion by champ

Champ by champion parameter로 들어온 championby 라는 키워드를 통해 위임해주면 이처럼 한줄로 해결할 수 있게 됩니다.


위임 된 클래스에서 변수를 선언하는 경우

class User(private val champ: Champion) : Champion by champ {
	override val hp = 300
}

fun main(){
    val user = User(Ezreal())
    user.info()
}

하지만, by 키워드를 사용하여 위임된 클래스에서 프로퍼티를 따로 설정해 두었을 때, delegate object인 user는 이를 모르게 됩니다. 즉, hp 300은 출력되지 않게 됩니다.

그렇다면 왜 Delegation을 사용하는가? 상속 받으면 되는 것 아닌가?

코틀린의 기본 라이브러리는 open되지 않은 final 클래스입니다.

코틀린에서는 표준 라이브러리의 무분별 상속을 지양합니다. 상속을 통해 클래스의 확장을 필요로 할 때가 있는데 위임을 사용하면 상속과 비슷하게 final 클래스의 모든 기능을 사용하면서, 동시에 기능을 확장할 수 있습니다.


다음 포스팅으로 이어집니다!
https://velog.io/@evergreen_tree/KotlinDelegation-2.-Delegated-Property


참고 자료
https://kotlinlang.org/docs/delegation.html#overriding-a-member-of-an-interface-implemented-by-delegation

profile
android_developer

2개의 댓글

comment-user-thumbnail
2022년 6월 21일

delegation... 델리게이션....델리만쥬...먹고싶다

1개의 답글