세상을 더 편리하게
728x90

연산자 오버로딩 전에

연산자 오버로딩을 알아보기전에 연산자가 작동하는 시스템에 대해 알아볼 필요가 있다.

모든 연산자는 매소드를 통해서 작동한다.

3 + 4 라는 연산을 한다고 하자.

하지만 프로그래밍상에는 3.plus(4) 라는 매소드가 작동하는 것이다.

그렇기에 연산자는 모두 매소드 형태로 작동됨을 인지해야 연산자 오버로딩을 이해하는데 편리하다.

산술 연산자

class Print(var usedPage: Int, var ink: Double) {
    operator fun plus(p: Print): Print {
        return Print(this.usedPage + p.usedPage, this.ink + p.ink)
    }

    override fun toString(): String {
        return "usedPage : " + this.usedPage + " | Ink : " + this.ink
    }
}

fun main() {
    var printer1 = Print(0, 50.0)
    var printer2 = Print(0, 50.0)

    printer1.usedPage++
    printer2.usedPage += 2

    val total = printer1 + printer2

    println(total.toString())
}

위의 코드블럭 블럭을 보면 18번째 코드를 보면 클래스간의 덧셈을 볼 수 있다.

이처럼 클래스 간의 덧셈을 도와주는 것이 연산자 오버로딩이다.

쉽게 생각해서 연산자를 override 한다고 생각하면 쉽다.

2 ~ 4 번째 코드가 연산자 오버로딩한 것이다. operator fun [연산자] 하는 형식을 띈다.

우리가 가장 먼저 떠오르는 산술 연산자 오버로딩은 다음과 같다.

  • plus +

  • minus -

  • times *

  • div /

  • rem %

  • rangeTo ..

15번째 코드줄도 printer1++ 형식으로 오버로딩 할 수 있다.

산술 연산자를 오버로딩하면 대입연산자도 자동적으로 오버로딩이 되어진다.

더보기
  • plusAssign +=

  • minusAssign -=

  • timesAssign *=

  • divAssign /=

  • remAssign %=

하지만 여기서 유의해야 할 점은 plus 매소드의 파라미터는 Print 클래스로 되어져 있다. 

매소드는 파라미터가 다르면 다른 매소드로 인식하기에 그렇기에 16번째 코드 += 대입연산자는 오버로딩이 안된 상태이다.

Int 형을 파라미터로 갖는 매소드를 추가해주어야 한다. 그러므로  

    operator fun plus(n: Int): Print {
        return Print(this.usedPage + n, ink)
    }

혹은

    operator fun plus(p: Any): Print {
        when (p) {
            is Print -> return Print(this.usedPage + p.usedPage, this.ink + p.ink)
            is Int -> return Print(this.usedPage + p, ink)
        }
        return this
    }

 방식을 코드에 더해줘야 한다.

접두사 / 접미사 연산자

class Print(var usedPage: Int, var ink: Double) {
    operator fun plus(p: Print): Print {
        return Print(this.usedPage + p.usedPage, this.ink + p.ink)
    }

    operator fun inc(): Print = Print(this.usedPage++, ink)

    override fun toString(): String {
        return "usedPage : " + this.usedPage + " | Ink : " + this.ink
    }
}

fun main() {
    var printer1 = Print(0, 50.0)
    val printer2 = Print(0, 50.0)

    printer1++
    printer2.usedPage += 2

    val total = printer1 + printer2

    println(total.toString())
}

 

  • inc ++

  • dec --

호출 연산자

 호출 연산자는 가볍게 생각해서 ( ) 괄호를 생각하면 된다. 호출 연산자는 함수 호출을 돕는데 사용된다.

class Example {
    operator fun invoke(msg:String){
        println(msg)
    }
}

fun main() {
    val exam = Example()

    exam.invoke("MSG")
    exam("STRING")
}
/*
MSG
STRING
*/

다음과 같이 프러퍼티(파라미터) 를 했을 때 작동하고 싶은 것들을 오버로딩 할 수 있다.

인덱스 접근 연산자

인덱스 접근 연산자는 배열의 게터/세터를 다룰 때 사용 한다.

a[4] -> a.get(4) 와 같은 의미이다.

또한

a[4] = 5 -> a.set(4, b) 와 같은 의미이다.

단일 연산자

표현식 의미
+a a.unaryPlus()
-a a.unaryMinus()
!a a.not()

범위 연산자

표현식 의미
a in b b.contains(a)
a !in b !b.contains(a)

동등성 연산자

표현식 의미
a == b a?.equals(b) ? : (b == null)
a != b !(a?.equals(b)) ? : (b == null)

비교 연산자

표현식 의미
a > b a.compareTo(b) > 0
a < b a.compareTo(b) < 0

 

728x90

'Programming > Kotlin' 카테고리의 다른 글

[Kotlin/코틀린] 입력과 출력  (0) 2020.10.03
[Kotlin] 제네릭 / Generic  (0) 2020.03.19
[Kotlin] 내부 클래스(2)  (0) 2020.03.18
[Kotlin] 내부 클래스(1)  (0) 2020.03.15
[Kotlin] 데이터 클래스  (0) 2020.03.15
profile

세상을 더 편리하게

@쵱니

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!