Book/Kotlin in Action

Kotlin in Action: 7.1 산술 연산자 오버로딩

도라프 2023. 1. 6. 12:59

7. 1 산술 연산자 오버로딩

오버로딩 : 한 클래스내에 같은 이름의 메서드를 여러개 정의 하는 것

 

코틀린에서는 특정 연산자의 역할을 함수로 정의할 수 있다. 이를 Convention(관례)이라고 한다.

 

가장 기본적인 예로는 산술 연산자가 있다.

 

자바에서는 원시 타입(primitive)에 대해서만 산술 연산자를 사용할 수 있고, 추가로 String에 대해 "+" 연산자를 사용할 수 있다.

 

이항 산술 연산 오버로딩

코틀린에서는 +, - 같은 산술 연산자를 오버로딩해서 사용할 수 있다.

객체끼리 더하거나 뺄 때, 원하는 동작을 함수 안에 구현하면 연산자를 통해 이를 표현할 수 있다.

 

data class Point(val x: Int, val y: Int) {
   operator fun plus(other: Point): Point {  //"plus" 라는 연산자 함수를 정의한다. 
      return Point(x + other.x, y + other.y)
   }
}

>>> val point1 = Point(10, 20)
>>> val point2 = Point(30, 40)
>>> println(point1 + point2)  //"+"로 계산하면 "plus"함수가 호출됨.

Point(x=40, y=60)

 

연산자를 오버로딩하는 함수 앞에는 plus 함수와 같이 함수명 앞에 operator 키워드를 붙여야 하며, 

operator 키워드를 붙임으로써 이 함수가 Convention(관례)을 따르는 함수임을 명확히 한다.

 

위의 예제에서 operator plus 함수를 선언하고 나면 이제 "+" 기호로 두 Point 객체를 더할 수 있다.

 

다음은 오버로딩이 가능한 이항 산술 연산자를 정리한 것이다.

Expression
Function name
a * b
times
a / b
div
a % b
mod
a + b
plus
a - b
minus

 

연산자를 정의할 때 두 피연산자가(연산자 함수의 두 파라미터)가 같은 타입일 필요는 없다. 또는 연산자 함수의 반환 타입이 꼭 두 피연산자 중 하나와 일치해야만 하는 것도 아니다.

 

 

Char 타입과 Int 타입으로 연산을 하고 결과는 String으로 반환하는 연산자 조합의 오버로딩 케이스

 

/* 결과 타입이 피연산자 타입과 전혀 다른 연산자 정의하기 */
operator fun Char.times(count: Int) : String {
   return this.toString().repeat(count)
}

>>> println('A' * 3)

AAA

 

복합 대입 연산자 오버로딩

+=, -= 등의 연산자는 복합 대입(compound assignment)연산자라 불린다.

"+" 대응 함수인 plus와 같은 연산자를 오버로딩하면 코틀린은 그와 관련된 연산자인 "+=" 도 자동으로 구현한다.

>>> var point = Point(1, 2)
>>> point += Point(3, 4)  // point = point + Point(3, 4)와 동일
>>> println(point)

Point(x=4, y=6)

 

단항 연산자 오버로딩

단항 연산자를 오버로딩하는 방법도 이항 연산자와 마찬가지로 미리 정해진 함수를 선언하면서 operator로 표시하면 된다.

operator fun Point.unaryMinus() : Point {  //단항연산자는 파라미터가 없습니다.
   return Point(-x, -y)  //각 좌표에 -(음수)를 취한 좌표를 반환
}

>>> val point = Point(10, 20)
>>> println(-point)

Point(x = -10, y = -20)

 

expression Function name
+a unaryPlus
-a unaryMinus
!a not
++a, a++ inc
--a, a-- dec

 

 

"++" 와 "--" 의 경우 inc(), dec()만 구현해두면 알아서 전위와 후위 증가/감소 연산을 한다.

 

operator fun Int.inc() = this + 2

>>> var number = 0
>>> println(number++)
0
>>> println(number)
2
>>> printlin(++number)
4