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

[Kotlin] μ—°μ‚°μž μ˜€λ²„λ‘œλ”© (Operator overloading)

interfacer_han 2024. 1. 29. 11:47

#1 λ©”μ†Œλ“œ μ˜€λ²„λ‘œλ”© (Method overloading)

class Calculator {
    // μ •μˆ˜ν˜• 두 개λ₯Ό λ”ν•˜λŠ” λ©”μ†Œλ“œ
    fun add(x: Int, y: Int): Int {
        return x + y
    }
 
    // μ‹€μˆ˜ν˜• 두 개λ₯Ό λ”ν•˜λŠ” λ©”μ†Œλ“œ
    fun add(x: Double, y: Double): Double {
        return x + y
    }
}

fun main() {
    val calculator = Calculator()
    
    // μ •μˆ˜ν˜• λ§μ…ˆ
    val result1 = calculator.add(3, 4)
    println("Result of integer addition: $result1") // 좜λ ₯ κ²°κ³Ό: 7
    
    // μ‹€μˆ˜ν˜• λ§μ…ˆ
    val result2 = calculator.add(2.5, 3.5)
    println("Result of double addition: $result2") // 좜λ ₯ κ²°κ³Ό: 6.0
}

λ©”μ†Œλ“œμ˜ 선언뢀에 λͺ…μ‹œλ˜λŠ” λ§€κ°œλ³€μˆ˜μ˜ 리슀트λ₯Ό λ©”μ†Œλ“œ μ‹œκ·Έλ‹ˆμ²˜(Method signature)라고 ν•œλ‹€. λ©”μ†Œλ“œ μ˜€λ²„λ‘œλ”©μ€ 이름이 κ°™μ§€λ§Œ λ©”μ†Œλ“œ μ‹œκ·Έλ„ˆμ²˜κ°€ λ‹€λ₯Έ λ©”μ†Œλ“œλ“€μ„ 각각 μ„œλ‘œ λ‹€λ₯Έ λ©”μ†Œλ“œλ‘œ μ·¨κΈ‰ν•˜λŠ” ν”„λ‘œκ·Έλž˜λ° 기법이닀.
 

#2 μ—°μ‚°μž μ˜€λ²„λ‘œλ”© (Operator overloading)

#2-1 κ°œλ…

λ©”μ†Œλ“œ μ˜€λ²„λ‘œλ”©μ΄ 'λ©”μ†Œλ“œλ₯Ό μ€‘λ³΅ν•΄μ„œ μ •μ˜'이라면, μ—°μ‚°μž(Operator) μ˜€λ²„λ‘œλ”©μ€ 'μ—°μ‚°μžλ₯Ό μ€‘λ³΅ν•΄μ„œ μ •μ˜'λ‹€. μ—°μ‚°μžλž€ 예λ₯Ό λ“€λ©΄ -1, 2 + 2, 4* 7 λ“±μ˜ μˆ˜μ‹μ— μžˆλŠ” μ—°μ‚°μž κΈ°ν˜Έλ“€μ„ λ§ν•œλ‹€.
 
λ©”μ†Œλ“œ μ˜€λ²„λ‘œλ”©μ—μ„œ λ©”μ†Œλ“œλ₯Ό κ΅¬λΆ„ν•˜λŠ” 핡심은 'λ©”μ†Œλ“œ μ‹œκ·Έλ‹ˆμ²˜'μ˜€λ‹€. μ—°μ‚°μž μ˜€λ²„λ‘œλ”©μ—λ„ 이λ₯Έλ°” 'μ—°μ‚°μž μ‹œκ·Έλ‹ˆμ²˜'의 역할을 μˆ˜ν–‰ν•˜λŠ” 무언가가 μžˆμ„κΉŒ? 그건 λ°”λ‘œ ν”Όμ—°μ‚°μž(Operation)λ‹€. 예λ₯Ό λ“€μ–΄, 71 - 16μ—μ„œ μ—°μ‚°μžλŠ” λ§ˆμ΄λ„ˆμŠ€ 기호고 ν”Όμ—°μ‚°μžλŠ” Intλ‹€. "ꡬꡬ" + "콘"μ—μ„œ μ—°μ‚°μžλŠ” ν”ŒλŸ¬μŠ€ 기호고, ν”Όμ—°μ‚°μžλŠ” String이닀.
 

#2-2 문법

// report card: μ„±μ ν‘œ
class ReportCard(val name: String, val score: Int) {
    
    operator fun plus(increment: Int): ReportCard {
        return ReportCard(name, score + increment)
    }

    // 'μ—°μ‚°μž μ˜€λ²„λ‘œλ”©'을 'λ©”μ†Œλ“œ μ˜€λ²„λ‘œλ”©'함
    operator fun plus(reportCard: ReportCard): ReportCard {
        return ReportCard(name + "와(κ³Ό) " + reportCard.name, score + reportCard.score)
    }

    operator fun minus(decrement: Int): ReportCard {
        return ReportCard(name, score - decrement)
    }

    // Kotlin λ‚΄ λͺ¨λ“  클래슀의 μ΅œμƒμœ„ 클래슀인 Any 클래슀의 λ©”μ†Œλ“œ equals()λ₯Ό override
    override operator fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (javaClass != other?.javaClass) return false

        other as ReportCard

        if (name != other.name) return false
        if (score != other.score) return false

        return true
    }

    override fun hashCode(): Int {
        var result = name.hashCode()
        result = 31 * result + score
        return result
    }
}

fun main() {
    var s1 = ReportCard("철수", 100)
    s1 = s1 - 50 + ReportCard("영희", 200)

    if (s1 == ReportCard("μ² μˆ˜μ™€(κ³Ό) 영희", 250)) {
        println("${s1.name}의 μ μˆ˜λŠ” ${s1.score}점") // 좜λ ₯ κ²°κ³Ό: μ² μˆ˜μ™€(κ³Ό) 영희의 μ μˆ˜λŠ” 250점
    }
}

μΈν„°νŽ˜μ΄μŠ€λ‚˜ ν΄λž˜μŠ€μ—μ„œ, ν•¨μˆ˜ ν‚€μ›Œλ“œμΈ fun μ•žμ— operator ν‚€μ›Œλ“œλ₯Ό 달아주면 λœλ‹€. 단, operatorλŠ” λͺ‡λͺ‡ μ§€μ •λœ μ΄λ¦„μ˜ ν•¨μˆ˜μ—λ§Œ 뢙일 수 μžˆλ‹€. 말 κ·ΈλŒ€λ‘œ μ—°μ‚°μžλ₯Ό μ˜€λ²„λ‘œλ”©ν•˜λŠ” 것이기 λ•Œλ¬Έμ—, ν”„λ‘œκ·Έλž˜λ¨Έλ“€ μ‚¬μ΄μ—μ„œ λͺ…μ‹œμ μœΌλ‘œ ν•©μ˜λœ μ—°μ‚°μžμ˜ 이름듀을 μ •ν•΄λ‘μ—ˆλ‹€. κ·Έ 정해진 이름을 가진 μ•žμ— μ•žμ—λ§Œ operator ν‚€μ›Œλ“œλ₯Ό 뢙일 수 μžˆλ‹€. μ—¬λ‹΄μœΌλ‘œ, Any.equal()을 overrideν•  λ•ŒλŠ” Any.hashCode()도 같이 overrideν•΄μ£Όμ–΄μ•Ό ν•œλ‹€κ³  ν•œλ‹€.
 
λ‹€μŒμ€ operator ν‚€μ›Œλ“œλ₯Ό 뢙일 수 μžˆλŠ” ν•¨μˆ˜μ˜ 이름과 κ·Έ 역할이닀.
 

#3 operator ν‚€μ›Œλ“œμš© ν•¨μˆ˜

#3-1 일반적인 ν•¨μˆ˜

 

Operator overloading | Kotlin

 

kotlinlang.org

μœ„ λ§ν¬μ—μ„œ #2-2의 μ½”λ“œμ™€ 같은 일반적이고 기본적인 operator용 ν•¨μˆ˜ 이름을 찾을 수 μžˆλ‹€.
 

#3-2 invoke()

interface Calculator {
    operator fun invoke(x: Int, y: Int): Int
    operator fun invoke(x: Double, y: Double): Double
}

class AddCalculator : Calculator {
    override operator fun invoke(x: Int, y: Int): Int {
        return x + y
    }

    override operator fun invoke(x: Double, y: Double): Double {
        return x + y
    }
}

fun main() {
    val calculator: Calculator = AddCalculator()

    val resultInt = calculator(3, 5)
    println("닡은 $resultInt") // 닡은 8

    val resultDouble = calculator(3.5, 5.5)
    println("닡은 $resultDouble") // 닡은 9.0
}

이와 같이 () μ—°μ‚°μžμ˜ λ™μž‘λ„ overrideν•  수 μžˆλ‹€. ν•΄λ‹Ή λ™μž‘μ— ν•΄λ‹Ήν•˜λŠ” ν•¨μˆ˜ 이름은 μ˜μ–΄λ‘œ 'ν˜ΈμΆœν•˜λ‹€'λΌλŠ” 의미λ₯Ό μ§€λ‹Œ invokeλ‹€.
 

#3-3 get(), set()

class DataContainer {
    private val data = mutableMapOf<String, Any>()

    operator fun get(key: String): Any? {
        return data[key]
    }

    operator fun set(key: String, value: Any) {
        data[key] = value
    }
}

fun main() {
    val container = DataContainer()

    // set() μ—°μ‚°μž μ˜€λ²„λ‘œλ”© μ‚¬μš©
    container["name"] = "철수"
    container["age"] = 25

    // get() μ—°μ‚°μž μ˜€λ²„λ‘œλ”© μ‚¬μš©
    val name = container["name"]
    val age = container["age"]

    println("이름은 $name(이)κ³  λ‚˜μ΄λŠ” $age") // 좜λ ₯ κ²°κ³Ό: 이름은 철수(이)κ³  λ‚˜μ΄λŠ” 25
}

Array의 μ–΄λ–€ μ›μ†Œμ— μ ‘κ·Όν•  λ•Œ μ“°λ˜ λŒ€κ΄„ν˜Έ κΈ°ν˜Έλ„ μ—°μ‚°μžλ‹€. 그렇기에 μ—°μ‚°μž μ˜€λ²„λ‘œλ”©μ΄ κ°€λŠ₯ν•˜λ‹€.

#3-4 getValue(), setValue()

 

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

#1 Delegated properties#1-1 κ°œμš” Delegated properties | Kotlin kotlinlang.orgμœ„μž„ ν”„λ‘œνΌν‹°λŠ”, getter와 setter λ‘œμ§μ„ λ‹€λ₯Έ 객체에 μœ„μž„(delegate)ν•˜λŠ” μ½”ν‹€λ¦° ν”„λ‘œνΌν‹°λ₯Ό μ˜λ―Έν•œλ‹€. λ³Έ κ²Œμ‹œκΈ€μ—μ„œλŠ” μœ„μž„ ν”„λ‘œνΌν‹°

kenel.tistory.com

getValue()와 setValue()λŠ” μœ„μž„ ν”„λ‘œνΌν‹°(Delegated properties) μ „μš© μ—°μ‚°μžλ‹€. μœ„ κ²Œμ‹œκΈ€μ—μ„œ μ •λ¦¬ν–ˆλ‹€.

 

#4 μš”μ•½

μ—°μ‚°μž μ˜€λ²„λ‘œλ”©μœΌλ‘œ μ‚¬μš©μž μ •μ˜ 클래슀λ₯Ό μœ μ—°ν•˜κ³  μš°μ•„ν•˜κ²Œ μ‚¬μš©ν•œλ‹€.