이동식 저장소

[Kotlin] 위임 본문

Primary/Kotlin

[Kotlin] 위임

해스끼 2021. 1. 6. 11:52

위임이란 어떤 클래스의 멤버를 참조 없이 호출하고 싶을 때 사용하는 선언 방식이다. 

클래스의 위임

다음의 코드를 보자.

// 1
interface Animal {
    fun eat()
}
// 2
class Cat : Animal {
    override fun eat() {
        println("eat() at Cat")
    }
}
// 3
val cat = Cat()
// 4
class Robot : Animal by cat
  1. 인터페이스 Animal을 정의하였다.
  2. 클래스 Cat을 선언하고, Animal을 구현하였다. Cat은 추상 클래스 또는 인터페이스가 아니므로 eat()을 정의해야 한다.
  3. Cat의 객체 cat을 만들었다.
  4. 클래스 Robot을 선언하고, Animal을 구현하였다. Robot 역시 eat()을 정의해야 할 것 같지만, by 키워드를 사용하여 cat에게 정의를 위임한다.

Roboteat()을 직접 구현하는 대신 cateat()을 대신 사용하는 것이다. 자바 바이트코드를 디컴파일해 보면 Robot에도 cateat()이 구현되어 있음을 확인할 수 있다.

위임받은 객체의 eat()을 호출한다.

위임을 왜 쓸까?

코틀린의 기본 라이브러리는 상속할 수 없도록 정의되어 있다. 실제로 List 등의 클래스는 모두 open이 아니다. 이렇게 함으로써 라이브러리의 무분별한 상속을 막을 수 있지만, 클래스의 기능을 확장하기 어려워지는 문제가 발생한다.

 

위임을 사용하면 실제로 상속하지는 않지만 상속과 비슷한 효과를 낼 수 있다. 즉 클래스의 모든 기능을 사용하는 동시에 기능을 추가로 구현할 수 있다. 다만 강의에서 예시가 주어지지 않아 정확한 코드는 잘 모르겠다.

클래스의 위임 예시

interface Animal {
    fun eat(): String
}

class Cat : Animal {
    override fun eat() = "eat() at Cat"
}

class Dog : Animal {
    override fun eat() = "eat() at Dog"
}

class AnimalModel(private val name: String, anim: Animal) : Animal by anim {
    fun animalInfo() {
        println("name: $name, eat: ${eat()}")
    }
}

fun main() {
    val dog = AnimalModel("doge", Dog())
    val cat = AnimalModel("nangman", Cat())
    dog.animalInfo()
    cat.animalInfo()
}

위임받은 클래스의 eat() 메소드가 실행되었음을 볼 수 있다.

Observable

프로퍼티의 값이 변경될 때 특정 함수를 호출한다.

class Person {
    // 초기값: 0
    var age: Int by Delegates.observable(0) { prop, old, new ->
        println("age: $old -> $new")
    }
}

fun main() {
    val me = Person()
    me.age = 22
    me.age = 23
}

유용하게 써먹을 수 있지 않을까? 값을 변경할 때마다 로그를 찍는다던가.

Vetoable

값을 갱신할 때, 조건에 맞지 않으면 갱신을 거부(veto)할 수 있다. 비토권 할 때의 veto 맞다.

fun main() {
    // 초기값 설정 가능(여기서는 0)
    var max: Int by Delegates.vetoable(0) { prop, old, new ->
        new > old
    }

    max = 50
    println("max: $max")

    max = 10 // veto!
    println("max: $max")
}

람다식이 true를 반환할 때만 값이 갱신된다. old는 이전 값, new는 새로 갱신하려는 값이다.

참고 문헌

Do it! Kotlin programming @ edwith boostcourse

 

코틀린 프로그래밍 기본 2/2(객체지향편)

부스트코스 무료 강의

www.boostcourse.org

Delegated Properties @ Kotlin

 

Delegated Properties - Kotlin Programming Language

 

kotlinlang.org

 

'Primary > Kotlin' 카테고리의 다른 글

[Kotlin] Coroutines - Basics  (0) 2021.01.19
[Kotlin] Sequence  (0) 2021.01.15
[Kotlin] Thread 생성 및 실행  (0) 2021.01.14
[Kotlin] Collections 확장 함수  (0) 2021.01.13
[Kotlin] 데이터 클래스  (0) 2021.01.08