조각들

 

클래스 위임

  • 특정 클래스에 자기 클래스가 할 일을 다른 클래스에 맡겨 처리하는 것을 말한다. 
  • 위임을 맡기는 클래스를 위탁자, 위임을 받아서 실제 처리하는 클래스를 수탁자라고 한다.
  • 코틀린에서는 이 관계를 by를 사용해서 쉽게 구성할 수 있다.

 

위임이 좋은 것은 다양한 기능을 하나의 클래스를 통해서 받고 처리할 수 있도록 구조화할 수 있기 때문이다.

동일한 일을 나눠서 처리하려면 공통된 인터페이스가 필요하다.

 

 

클래스 위임 처리

//같은 결과를 반환하는 두 case

val b = BaseImpl(10)
Derived(b).say()

class Derived_() : Base by BaseImpl(10)
Derived_().say()

//베이스 클래스 구현 : 10
//베이스 클래스 구현 : 10

 

생성자의 매개변수 속성으로 위임 처리

val ps = Person("사람") // Person은 인터페이스 Sayable을 상속받는 클래스
val pt = Pet("개") // Pet은 인터페이스 Sayable을 상속받는 클래스

class Saying(val say : Sayable) : Sayable by say //매개변수로 전달한 객체로 위임 처리

Saying(ps).say()
Saying(pt).say()

//안녕하세요 : 사람
//멍멍멍 : 개

 

상속관계 클래스 위임 처리 가능

class Screen(val showable: Showable): Showable by showable

val view = View() //View는 Showable 인터페이스를 상속받는 클래스
val customView = CustomView() //CustomView는 View를 상속받는 클래스

Screen(view).show() 
Screen(customView).show()

//View 클래스의 show()
//CustomView 클래스의 show()

계층구조를 가져도 위탁자 클래스와 동일한 인터페이스 구현이 되면 이 인터페이스를 기준으로 위임관계를 구성할 수 있다.

 

 

여러 인터페이스로 클래스 위임 처리

class Screen(val showable: Showable, val viewable: Viewable): Showable by showable, Viewable by viewable

val show = Show()
val view = View()

Screen(show, view).show() //View.show()
Screen(show, view).view() //CustomView.show()

//Show 클래스의 show()
//View 클래스의 view()

 

 

속성 위임

  • 클래스 위임에도 by 예약어를 사용했듯이 속성에도 by로 위임을 처리할 수 있다.
  • 보통 코틀린 내부적으로 위임을 처리할 수 있는 notNull, vetoable, observable 메서드를 제공한다. 또한, 지연처리를 하는 lazy 함수도 사용할 수 있다.
  • 속성에 대한 위임은 속성을 사용할 때 특정한 값을 세팅해서 처리하는 것이다. 이때 Delefates 객체의 notNull, observable, vetoable를 사용한다.

 

 

notNull 위임처리

  • 속성의 지연초기화는 lateinit 예약어로 처리할 수 있다. 이 방식에서 정수와 실수 프리미티브가 사용되는 자료형은 지연초기화를 할 수 없다.
  • 속성 위임을 by로 사용하고 Delegates.notNull 메서드를 사용하면 프리미티브도 위임을 통한 지연초기화가 가능하다.
  • Delegates.notNull은 val 속성으로 지정할 때는 사용할 수 없다.
import kotlin.properties.Delegates //코틀린 속성 지연 처리 object

lateinit var str : String //최상위 속성 지연 초기화는 참조 객체만 가능
//lateinit var int : Int //최상위 속성 지연 초기화할 때는 기본 자료형은 불가

var str1 : String by Delegates.notNull<String>()
var int1 : Int by Delegates.notNull<Int>()

//val str2: String by Delegates.notNull<String>() //val은 재할당 금지라서 지연초기화 사용 못함
//val int2: Int by Delegates.notNull<Int>() //val은 재할당 금지라서 지연초기화 사용 못함

str = "초기화 처리"
str1 = "초기화 처리"
int1 = 100

println("lateinit 처리 = $str")
println("notnUll String 처리 = $str1")
println("notNull Int. 처리 = $int1")

//lateinit 처리 = 초기화 처리
//notNull String 처리 = 초기화 처리
//notNull Int. 처리 = 100

 

 

속성 변경 관찰

import kotlin.properties.Delegates

var observed = false
var max: Int by Delegates.observable(0) {
    _, oldValue, newValue ->
    println("변경전 : $oldValue 변경후 : $newValue")
    observed = true
}

println(max)
println("관찰상태 = ${observed}")
max = 10
println(max)
println("관찰상태 = ${observed}")

//0
//관찰상태 = false
//변경전 : 0 변경후 : 10
//10
//관찰상태 = true

Q. liveData와 비교해서 Delegates.observable를 썼을 때의 이점이 있을까요?

 

 

특정 조건이 일치할 때만 속성 위임 변경

  • 속성 위임을 vetoable 메서드로 처리할 경우는 조건이 만족할 때만 속성값을 변경한다.
  • 이 속성의 필드를 바꾸면 실제 짝수일 경우에만 값이 변경된다.
var vetoableField: Int by Delegates.vetoable(0) { //변경 거부 여부
    _, old, new -> //속성 변경 전
    println("변경전 : $old, 변경후 : $new") //변경 상태 확인
    new % 2 == 0 //조건이 참인 경우: 짝수 값일 경우만 갱신
}

 

 

속성과 지역변수 지연초기화

  • 속성 위임을 사용하는 지연처리는 val 속성과 val 변수에서 가능하다.
  • 함수 내의 지역변수도 var는 lateinit, val은 by lazy로 지연초기화 처리를 할 수 있다.

 

Q. 맵 자료형을 사용한 속성 위임 처리는 이점, 활용 목적이 무엇인가요?

'Kotlin > 스터디' 카테고리의 다른 글

코틀린 스터디 - 10장  (0) 2023.09.17
코틀린 스터디 - 9장  (1) 2023.09.10
코틀린 스터티 - 8장  (0) 2023.09.03
코틀린 스터디 - 6장  (0) 2023.08.20
코틀린 스터디 - 5장  (0) 2023.08.13