κΉ¨μ•Œ κ°œλ… πŸ“‘/Kotlin

[Kotlin] μœ„μž„ ν”„λ‘œνΌν‹° (Delegated properties)

interfacer_han 2024. 7. 22. 22:45

#1 Delegated properties

#1-1 κ°œμš”

 

Delegated properties | Kotlin

 

kotlinlang.org

μœ„μž„ ν”„λ‘œνΌν‹°λŠ”, getter와 setter λ‘œμ§μ„ λ‹€λ₯Έ ν΄λž˜μŠ€μ— μœ„μž„(delegate)ν•˜λŠ” μ½”ν‹€λ¦° ν”„λ‘œνΌν‹°λ₯Ό μ˜λ―Έν•œλ‹€. λ³Έ κ²Œμ‹œκΈ€μ—μ„œλŠ” μœ„μž„ ν”„λ‘œνΌν‹°μ˜ κΈ°μ œμ— λŒ€ν•΄ νƒκ΅¬ν•˜κ³  또 μœ„μž„ ν”„λ‘œνΌν‹°λ₯Ό κ°„λ‹¨νžˆ κ΅¬ν˜„ν•΄λ³Έλ‹€.

 

#1-2 μœ„μž„(delegate)의 의미

 

[Kotlin] ν”„λ‘œνΌν‹°(Property)

#1 ν•„λ“œμ™€ ν”„λ‘œνΌν‹° #1-1 ν”„λ‘œνΌν‹°μ˜ κ°œλ… // Java String name = "steve"; // Field System.out.println("my name is" + name); name = "kevin"; --- // Kotlin var name : String = "steve" // Property println("my name is" + name) name = "kevin" μ½”ν‹€

kenel.tistory.com

μœ„ κ²Œμ‹œκΈ€μ—μ„œ 보듯, μ½”ν‹€λ¦° ν”„λ‘œνΌν‹°λŠ” λͺ…μ‹œμ  get() 및 set() ꡬ문으둜 getter 및 setterλ₯Ό μ»€μŠ€ν…€ν•  수 μžˆλ‹€. 이 μ»€μŠ€ν…€ getter 및 setterλŠ” ν•΄λ‹Ή 객체에 ν•œμ •λ˜μ–΄ μ μš©λœλ‹€. λ”°λΌμ„œ λͺ¨λ“ˆν™”λ₯Ό ν†΅ν•œ μž¬μ‚¬μš©μ΄ λΆˆκ°€λŠ₯ν•˜λ‹€. 이 λ•Œ μœ„μž„ ν”„λ‘œνΌν‹°λ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€.

 

κ·Έλ ‡λ‹€λ©΄ μœ„μž„μ΄λž€ 무슨 의미둜 쓰인 단어인가? μ–΄λ–€ 클래슀(μ΄ν•˜ A 클래슀) νƒ€μž…μΈ ν”„λ‘œνΌν‹° aκ°€ μžˆλ‹€κ³  ν•΄λ³΄μž. a의 get() 및 set()을 μ»€μŠ€ν…€ν•˜λ €κ³  ν•œλ‹€. μœ„ 링크에 μžˆλŠ” κ²Œμ‹œκΈ€μ²˜λŸΌ get() 및 set()을 ν”„λ‘œκ·Έλž˜λ¨Έκ°€ 직접 μ»€μŠ€ν…€ν•˜λŠ” 방법이 μžˆμ„ 것이닀. 이 λ•Œ κ·Έ λŒ€μ‹  λ‹€λ₯Έ 클래슀(μ΄ν•˜ B 클래슀)에 μ •μ˜λœ getter 및 setterλ₯Ό 가져와 a의 get() 및 set()에 λŒ€μž…ν•˜λŠ” 것이 λ°”λ‘œ 'μœ„μž„'의 μ˜λ―Έλ‹€. λ‹€μ‹œ λ§ν•˜μžλ©΄ μ–΄λ–€ 객체의 값을 읽고 μ“°λŠ” λ™μž‘μ„ 직접 κ΅¬ν˜„ν•˜μ§€ μ•Šκ³ , λ‹€λ₯Έ ν΄λž˜μŠ€μ—κ²Œ λ§‘κΈ°λŠ” 것이닀. λ•Œλ¬Έμ— 클래슀 BλŠ” 읽고 μ“°λŠ” λ™μž‘μ— λŒ€ν•œ μ—°μ‚°μž μ˜€λ²„λ‘œλ”© λ©”μ†Œλ“œκ°€ λ°˜λ“œμ‹œ μ‘΄μž¬ν•΄μ•Ό ν•œλ‹€. 그리고 κ·Έ μ—°μ‚°μž μ˜€λ²„λ‘œλ”© λ©”μ†Œλ“œλŠ” operator fun getValue() 및 operator fun setValue()으둜 μ•½μ†λ˜μ–΄ μžˆλ‹€.

 

μ£Όμ˜ν•  점은, operator fun getValue() 및 operator fun setValue()λŠ” μœ„μž„ μ „μš© μ—°μ‚°μž μ˜€λ²„λ‘œλ”© λ©”μ†Œλ“œλΌλŠ” 것이닀. 즉, 이 λ©”μ†Œλ“œλ₯Ό κ°€μ§€κ³  μžˆλ‹€κ³  ν•΄μ„œ ν‰μ†Œμ—λ„ ν•΄λ‹Ή B ν΄λž˜μŠ€κ°€ 이 클래슀λ₯Ό μ΄μš©ν•΄ μžμ‹ μ˜ 값을 getν•˜κ±°λ‚˜ setν•˜μ§€λŠ” μ•ŠλŠ”λ‹€λŠ” μ–˜κΈ°λ‹€. 였직 μœ„μž„ ν”„λ‘œνΌν‹°μ—κ²Œ getter와 setterλ₯Ό μ œκ³΅ν•  λ•Œ μ „λ‹¬λ˜λŠ” λͺ©μ μœΌλ‘œ μ‘΄μž¬ν•˜λŠ” λ©”μ†Œλ“œλ‹€. λ‹€μ‹œ λ§ν•˜μžλ©΄ B 클래슀의 get()은 getValue()와 κ΄€λ ¨ μ—†λŠ” λ©”μ†Œλ“œκ³ , λ§ˆμ°¬κ°€μ§€λ‘œ B 클래슀의 set()은 setValue()μ™€λŠ” λ‹€λ₯Έ λ©”μ†Œλ“œλ‹€.

 

#1-3 μœ„μž„(Delegate object) 객체: μœ„μž„ ν”„λ‘œνΌν‹°μ˜ get 및 set을 λŒ€μ‹ ν•˜λŠ” 클래슀

import kotlin.reflect.KProperty

// 클래슀 B: μœ„μž„ 객체(Delegate object)
class MyDelegate {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return "Delegated property"
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        println("Delegated property never set to $value")
    }
}

#1-2μ—μ„œ λ§ν•œ B 클래슀의 κ°€μž₯ 기본적인 ν˜•νƒœλ‹€. B ν΄λž˜μŠ€μ™€ 같은 역할을 μˆ˜ν–‰ν•˜λŠ” 클래슀λ₯Ό μœ„μž„ 객체(Delegate object)라 ν•œλ‹€. getValue() λ°˜ν™˜ν˜• 및 setValue()의 λ§€κ°œλ³€μˆ˜ νƒ€μž…μ„ 보아, μœ„ μ˜ˆμ‹œ μ½”λ“œλŠ” #1-2μ—μ„œ λ§ν•œ A ν΄λž˜μŠ€κ°€ String일 λ•Œλ§Œ μœ„μž„μ„ μˆ˜ν–‰ν•  수 μžˆμ„ 것이닀. MyDelegateμ—κ²Œ get() 및 set()을 μœ„μž„ν•œ String ν”„λ‘œνΌν‹°κ°€ μ‘΄μž¬ν•œλ‹€λ©΄ κ·Έ ν”„λ‘œνΌν‹°μ˜ 값은 "Delegated property"둜 μ˜μ›νžˆ κ³ μ •λ˜κ³ , 아무리 값을 λ°”κΎΈλ €λŠ” μ‹œλ„λ₯Ό 해도 κ·Έ λ•Œλ§ˆλ‹€ μ½˜μ†”μ— "Delegated property never set to $value"λ₯Ό 내뱉을 뿐 μ‹€μ œ 값을 λ°”κΏ€ μˆ˜λŠ” 없을 것이닀.

 

#1-4 μœ„μž„ ν”„λ‘œνΌν‹° μ„ μ–Έ ν˜•μ‹

val/var <property name>: <Type> by <expression>

#1-2μ—μ„œ λ§ν•œ ν”„λ‘œνΌν‹° aλŠ” <property name>을 μ˜λ―Έν•œλ‹€. AλŠ” <Type>에 λŒ€μ‘λœλ‹€. BλŠ” <expression>에 λŒ€μ‘λœλ‹€. μ΄λ•Œ aλŠ” val일 μˆ˜λ„ 있고 var일 μˆ˜λ„ μžˆλŠ”λ°, val인 경우 <expression>은 operator fun getValue()λ§Œμ„ 갖좰도 λœλ‹€. ν•˜μ§€λ§Œ var이라면 μΆ”κ°€λ‘œ operator fun setValue()κΉŒμ§€ κ°–μΆ°μ•Ό <property name>을 μœ„μž„ ν”„λ‘œνΌν‹°λ‘œ λ§Œλ“€ 수 μžˆλ‹€.

 

#2 μ½”λ“œ μ˜ˆμ‹œ

import kotlin.reflect.KProperty

// 클래슀 B: μœ„μž„ 객체(Delegate object)
class Delegate {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return "Delegated property"
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        println("Delegated property never set to $value")
    }
}

// ν”„λ‘œνΌν‹° a: μœ„μž„ ν”„λ‘œνΌν‹°(Delegated property)
var a: String by Delegate()

fun main() {
    println(a)
    a = "Hello!"
    println(a)
}

/* 좜λ ₯ κ²°κ³Ό

Delegated property
Delegated property never set to Hello!
Delegated property

*/

 

#3 μš”μ•½

μž¬μ‚¬μš© κ°€λŠ₯ν•œ getter/setter (= μœ„μž„ 객체)둜 μœ„μž„ ν”„λ‘œνΌν‹°λ₯Ό λ§Œλ“€μ–΄λ‚Έλ‹€.