본문 바로가기

Kotlin

Kotlin - Operator overloading (연산자 오버로딩)

https://kotlinlang.org/docs/operator-overloading.html

 

Operator overloading | Kotlin

 

kotlinlang.org

코틀린은 타입에 대한 기본연산자 들의 동작을 (재)정의 할수 있다. 이를 위해서는 사전에 정해진이름의 함수를 타입의 멤버 함수나 확장 함수 형태로 제공해야 한다. 이 타입은 이항연산자에서 피 연산자(좌항)가 된다.

연산자를 재정의 하기 위해서는 해당 함수에 operator 수정자를 붙인다. 이 함수를 overriding 하는 경우엔 생략 할 수 있다.

interface IndexedContainer {
    // 연산자를 정의할때는 operator 수정자를 붙인다.
    operator fun get(index: Int)
}

class OrderList: IndexedContainer {
//    operator 수정자가 붙은 함수를 override 할때는 operator 수정자를 생략 할 수 있다.
    override fun get(index: Int) {
        /* ... */
    }
}

 

단항 연산자 (Unary operations)

Unary prefix operators

Expression Translated to
+a a.unaryPlus()
-a a.unaryMinus()
!a a.not()

위 연산자를 사용하면(+a 를 예로) 컴파일러는 아래의 순서대로 동작한다.

  1. a의 타입을 정한다. T 라고 하자
  2. operator 수정자가 붙어있고 파라미터가 없는, 수신자 타입이 T인 unaryPlus 함수를 찾는다.
  3. 해당 함수가 없거나 애매하면 컴파일 오류를 발생시킨다.
  4. 해당 함수가 있으면, +a는 R 타입을 반환한다.

특정 타입에 대해 단항 연산자를 정의하고, 사용하는 방법은 아래와 같다.

data class Point(val x: Int, val y: Int)
operator fun Point.unaryMinus() = Point(-x, -y)

fun main() {
    val point = Point(10, 20)
    println(-point) // Point(x=-10, y=-20)
}

Increments and decrements

Expression Translated to
a++ a.inc()
a-- a.dec()

inc(), dec() 함수는 반환값이 존재해야 하며 이 반환값은 ++, -- 연산자가 사용된 변수에 할당된다.

  1. a의 타입을 정한다. T 라고 하자
  2. operator 수정자가 붙어있고 파라미터가 없는, 수신자 타입이 T인 unaryPlus 함수를 찾는다.
  3. 해당 함수의 반환타입이 T의 자식 타입인지 확인한다.

동작 방식은 아래와 같다.

  1. a의 값을 a0에 저장한다.
  2. a0.inc()의 결과를 a에 할당한다. 
  3. a0의 값을 표현식의 결과로 반환한다.

++a나 --a의 경우 동일하게 동작하며, 동작 방식이 아래처럼 다르다.

  1. a.inc()의 결과를 a에 할당한다.
  2. a의 값을 표현식의 결과로 반환한다.

2항 연산자 (Binary operations)

Arithmetic operators

Expression Translated to
a + b a.plus(b)
a - b a.minus(b)
a * b a.times(b)
a / b a.div(b)
a % b a.rem(b)
a..b a.rangeTo(b)
a..<b a.rangeUntil(b)

in operator

Expression Translated to
a in b b.contains(a)
a !in b !b.contains(a)

Indexed access operator

Expression Translated to
a[i] a.get(i)
a[i, j] a.get(i, j)
a[i_1, ..., i_n] a.get(i_1, ..., i_n)
a[i] = b a.set(i, b)
a[i, j] = b a.set(i, j, b)
a[i_1, ..., i_n] = b a.set(i_1, ..., i_n, b)

invoke operator

Expression Translated to
a() a.invoke()
a(i) a.invoke(i)
a(i, j) a.invoke(i, j)
a(i_1, ..., i_n) a.invoke(i_1, ..., i_n)

Argumented assignments

Expression Translated to
a +=b  a.plusAssign(b)
a -= b a.minusAssign(b)
a *= b a.timesAssign(b)
a /= b a.divAssign(b)
a %= b a.,remAssign(b)

Equality and inequality operators

Expression Translated to
a == b a?.equals(b) ?: (b === null)
a != b !(a?.equals(b) ?: (b === null))

Comparison operators

Expression Translated to
a > b a.compareTo(b) > 0
a < b a.compareTo(b) < 0
a >= b a.compareTo(b) >= 0
a <= b a.compareTo(b) <= 0
반응형