Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- AWS
- GitHub
- 쿠링
- relay
- Kotlin
- Coroutine
- androidStudio
- boj
- pandas
- Codeforces
- 프로그래머스
- android
- Gradle
- TEST
- ProGuard
- Python
- 백준
- MyVoca
- Compose
- livedata
- 암호학
- 코드포스
- Coroutines
- textfield
- 코루틴
- Rxjava
- architecture
- Hilt
- activity
- MiTweet
Archives
- Today
- Total
이동식 저장소
[Kotlin] 위임 본문
위임이란 어떤 클래스의 멤버를 참조 없이 호출하고 싶을 때 사용하는 선언 방식이다.
클래스의 위임
다음의 코드를 보자.
// 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
- 인터페이스 ``Animal``을 정의하였다.
- 클래스 ``Cat``을 선언하고, ``Animal``을 구현하였다. ``Cat``은 추상 클래스 또는 인터페이스가 아니므로 ``eat()``을 정의해야 한다.
- ``Cat``의 객체 ``cat``을 만들었다.
- 클래스 ``Robot``을 선언하고, ``Animal``을 구현하였다. ``Robot`` 역시 ``eat()``을 정의해야 할 것 같지만, ``by`` 키워드를 사용하여 ``cat``에게 정의를 위임한다.
즉 ``Robot``은 ``eat()``을 직접 구현하는 대신 ``cat``의 ``eat()``을 대신 사용하는 것이다. 자바 바이트코드를 디컴파일해 보면 ``Robot``에도 ``cat``의 ``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
'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 |
Comments