자바에서는 원시 타입에 대해서만 산술 연산자를 사용할 수 있고, 추가로 String에 대해 + 연산자를 사용할 수 있다. 코틀린에서는 원시 타입 외 다른 클래스에 대해 일반 산술 연산자를 정의해 사용할 수 있다.

이항 산술 연산 오버로딩

Point에 두 점을 더하는 연산을 추가해보자.

data class Point(val x: Int, val y: Int) {
    operator fun plus(other: Point): Point {
        return Point(x + other.x, y + other.y)
    }
}

fun main() {
    val p1 = Point(1, 1)
    val p2 = Point(2, 2)
    println(p1 + p2) // Point(x=3, y=3)
}

plus 함수 앞에 operator 키워드를 붙여야 한다. 연산자를 오버로딩하는 함수 앞에는 꼭 operator가 있어야 한다. operator를 붙이지 않고 관례에서 사용하는 함수 이름을 사용하면 'operator' modifier is required on 'plus' in 'Point' 와 같은 오류가 나온다.

p1 + p2p1.plus(p2)로 컴파일된다.

연산자를 멤버 함수로 만드는 대신 확장 함수로 정의할 수도 있다.

operator fun Point.plus(other: Point): Point {
    return Point(x + other.x, y + other.y)
}

외부 함수의 클래스에 대한 연산자를 정의할 때는 관례를 따르는 이름의 확장 함수로 구현하는 게 일반적인 패턴이다.

코틀린에서는 프로그래머가 직접 연산자를 만들어 사용할 수 없고 언어에서 미리 정해둔 연산자만 오버로딩할 수 있으며, 관례에 따르기 위해 클래스에서 정의해야 하는 이름이 연산자별로 정해져 있다.

함수 이름
a * b times
a / b div
a % b mod(1.1부터 rem)
a + b plus
a - b minus

직접 정의한 함수를 통해 구현하더라도 연산자 우선순위는 언제나 표준 숫자 타입에 대한 연산자 우선순위와 같다. 예를 들어 a + b * c라는 식에서는 언제나 곱셈이 항상 덧셈보다 먼저 수행된다.

연산자를 정의할 때 두 피연산자(연산자 함수의 두 파라미터)가 같은 타입일 필요는 없다. 예를 들어 어떤 점을 비율에 따라 확대/축소하는 연산자를 정의해보자. 이를 사용해 여러 다른 좌표계 사이에 점을 변환할 수 있다.

operator fun Point.times(scale: Double): Point {
    return Point((x * scale).toInt(), (y * scale).toInt())
}

fun main() {
    val p = Point(10, 20)
    println(p * 1.5) // Point(x=15, y=30)
}

코틀린 연산자가 자동으로 교환 법칙(commutativity, a op b == b op a인 성질)을 지원하지 않는다. 사용자가 p * 1.5 외에 1.5 * p라고도 쓸 수 있어야 한다면 p * 1.5와 같은 식에 대응하는 연산자 함수인 operator fun Double.times(p:Point) : Point를 더 정의해야 한다.

연산자 함수의 반환 타입이 꼭 두 피연산자 중 하나와 일치해야만 하는 것도 아니다.

operator fun Char.times(count: Int): String {
    return toString().repeat(count)
}

fun main() {
    println('a' * 3)
}

일반 함수와 마찬가지로 operator 함수도 오버로딩할 수 있다. 따라서 이름은 같지만 파라미터 타입이 서로 다른 연산자 함수를 여럿 만들 수 있다.

비트 연산자에 대해 특별한 연산자 함수를 사용하지 않는다.

코틀린은 표준 숫자 타입에 대해 비트 연산자를 정의하지 않는다. 따라서 커스텀 타입에서 비트 연산자를 정의할 수도 없다. 대신에 중위 연산자 표기법을 지원하는 일반 함수를 사용해 비트 연산을 수행한다. 커스텀 타입에서도 그와 비슷한 함수를 정의해 사용할 수 있다.