연산자 오버로딩

tkppp·2021년 12월 27일
0

Kotlin

목록 보기
9/11

연산자 오버로딩

자바에서는 연산자 오버로딩을 허용하지 않는다. 원시 타입에 한해서만 산술 연산자를 사용할 수 있었고 예외적으로 String 클래스에 대해 + 연산자를 사용할 수 있었다. 하지만 코틀린을 이를 허용한다. 연산자 오버로딩은 클래스 메소드에 operator 키워드를 붙혀 만든다. 또는 확장함수를 통해 정의하는 것도 가능하다. 이 때 연산자를 새로 만들 수는 없고 코틀린에서 지정한 연산자만 오버로딩할 수 있다.

산술 연산자 오버로딩(+,-,*,/,%)

이항 산술 연산자 오버로딩

함수 이름
a * btimes
a / bdiv
a % bmod(1.1부터 rem)
a + bplus
a + bminus

산술 연산자 오버로딩의 위의 5개 연산자에 한에서 가능하다.

data class Point(val x: Int, val y: Int){
    operator fun plus(other: Point) = Point(x + other.x, y + ohter.y)
    operator fun times(scale: Double) = Point((x * scale).toInt(), (y * scale).toInt())
}

val p = Point(10, 15)
println(p + Point(-10, -15)	// Point(x = 0, y = 0) 출력
println(p * 1.5)		// Point(x = 15, y = 22) 출력

교환 법칙

연산자 오버로딩을 했다고 해서 코틀린에서 교환법칙을 자동으로 지원하지는 않는다. 만약 위의 예제에서 곱셉의 교환법칙을 지원하기 위해서는 Double 클래스에 아래와 같이 연산자를 오버로딩해야한다.

operator fun Double.times(p: Point) = Point((this * p.x).toInt(), (this * p.y).toInt())

복합 대입 연산자 오버로딩

+=, -= 등의 연산과 대입을 동시에 수행하는 연산자를 복합 대입 연산자라고 한다. += 은 plusAsign 함수를 정의하여 오버로딩 할 수 있다. 나머지 복합 대입 연산자의 이름은 산술 연산자 이름에 Asign을 붙여주면 된다.

이런 연산자는 주로 참조를 변경하는 것이 아닌 변경 가능한 객체 내부의 값을 변경하기 위함이다. 예를들어 MutableList의 += 은 새로운 원소를 리스트에 집어 넣는다.

operator fun <T> MutableCollection<T>.plusAssign(element: T){
    this.add(element)
}

주의점

어떤 클래스가 +=과 +의 연산자 오버로딩이 정의되어 있고 +=에 + 연산이 가능한 경우 컴파일러는 에러를 발생시킨다.

a += b

a = a.plus(b)
a.plusAsign(b)

plus와 plusAsign은 동작하는 방식이 완전히 다른다. plus는 참조를 변경하지만 plusAsign은 참조를 변경하지 않고 내부 값을 변경한다.

따라서 산술 연산자 오버로딩과 복합 대입 연산자들 동시에 정의하지 않는게 좋다.

단항 연산자 오버로딩

함수 이름
+aunaryPlus
-aunaryMinus
!anot
++a, a++inc
--a, a--dec

단항 연산자 오버로딩도 이항 연산자와 마찬가지로 할 수 있다.

비교 연산자 오버로딩

자바에서는 객체에 대한 비교 연산자를 사용할 수 없었다. equals나 compareTo를 호출하여 비교 연산을 수행했다. 하지만 코틀린은 비교 연산에 대한 오버로딩을 지원한다.

순서 연산자 compareTo

비교가 필요한 알고리즘에 사용할 클래스는 Comparable 인터페이스를 구현해야한다. 코틀린에서는 Comparable 인터페이스의 compareTo 메소드가 구현되어 있다면 순서 연산자(<, >, >=, <=)를 이용한 비교가 가능하다.

연산자 오버로딩이지만 Comparable 인터페이스에 operator 식별자가 선언되어 있으므로 오버라이드 할 때 operator 식별자를 붙일 필요는 없다.

0개의 댓글