관리 메뉴

너와 나의 스토리

[Kotlin] 위임 프로퍼티(delegated property) / by lazy()를 사용한 초기화 지연 / lateinit 본문

Programming Language/Kotlin

[Kotlin] 위임 프로퍼티(delegated property) / by lazy()를 사용한 초기화 지연 / lateinit

노는게제일좋아! 2021. 6. 29. 10:29
반응형

위임 프로퍼티

  • 위임은 객체가 직접 작업을 수행하지 않고 다른 도우미 객체가 그 작업을 처리하게 맡기는 디자인 패턴을 말한다.
  • '클래스 위임' 참고 
  • 문법:
    • class Foo {
          var p: Type by Delegate()
      }
    • p 프로퍼티는 접근자 로직을 다른 객체(Delegate 클래스)에게 위임
    • Delegate 클래스에 위임하기 위해서는 Delegate 클래스에 getValue와 setValue 메서드가 있어야 한다.
  • 예제:
    • class Delegate(var value: String) {
          operator fun getValue(foo: Foo, property: KProperty<*>): String {
              return value
          }
          operator fun setValue(foo: Foo, property: KProperty<*>, value: String) {
              this.value = value
          }
      }
      
      class Foo {
          var f: String by Delegate("value1")
      }
      
      fun main(args: Array<String>) {
          val foo = Foo()
          println(foo.f) // output: value1
      }

 

 

 

 

by lazy()를 사용한 프로퍼티 초기화 지연

  • 지연 초기화(lazy initialization)는 객체의 일부분을 초기화하지 않고 남겨뒀다가 실제로 그 부분의 값이 필요한 경우 초기화할 때 흔히 쓰이는 패턴이다.
  • 초기화 과정에 자원을 많이 사용하거나 객체를 사용할 때마다 꼭 초기화하지 않아도 되는 프로퍼티에 대해 지연 초기화 패턴을 사용할 수 있다.
  • 예: person 클래스가 자신이 작성한 이메일의 목록을 제공
    •  
      • getEmailsFromDB(): 데이터베이스에서 email들을 가져오는 것(대체)
      • loadEmails(person): 디비에서 가져온 이메일들 중 person의 메일만 추출하여 리턴
    • data class Person(val name: String, val age: Int) { val emails = loadEmails(this) } data class Email(val name: String, val title: String, val content: String) fun getEmailsFromDB(): List<Email> { val email1 = Email("hororolol", "title1", "content") val email2 = Email("hororolol", "title2", "content") val email3 = Email("new man", "title2", "content") return listOf(email1, email2, email3) } fun loadEmails(person: Person): List<Email> { val emails = getEmailsFromDB() val myEmails = ArrayList<Email>() for (email in emails) { if (email.name.equals(person.name)) { myEmails.add(email) } } return myEmails }
    • 이메일 프로퍼티의 값을 최초로 사용할 때 디비에서 이메일 정보를 가져오자. -> 프로퍼티 초기화 지연
      • data class Person(val name: String, val age: Int) {
            val emails by lazy { loadEmails(this) }
        }
        • 이렇게 하면 최초로 Person의 emails를 조회할 때 loadEmails() 함수가 작동된다. 

 

lateinit: 가변 참조를 지연 초기화

  • 가변 참조에 대해 by lazy를 사용할 수 없다. 가변 참조를 꼭 지연 초기화해야 한다면 lateinit 키워드를 사용할 수 있다.
  • 예:
    •  
    • lateinit var name: String name = getName()
  • 이런 식으로 구성하면 널이 될 수 있는 타입을 사용하지 않아도 된다.
  • 하지만 프로퍼티를 다루고자 DI  프레임워크 등으로 외부에서 필드 초기화를 진행하는 경우를 제외하면 by lazy와 비교할 때 장점이 전혀 없다.

 

 

 

 

출처:

- [Kotlin IN ACTION]

- [코틀린을 다루는 기술]

 

반응형
Comments