2 + 3 % 4 * 5
// 이는 17 과 같음
2 + ((3 % 4) * 5)
클래스와 구조체는 기존 연산자에 자신만의 구현을 제공할 수 있다. 이를 기존 연산자의 중복 정의 (overloading) 라고 한다.
다음 예제는 이번 계산기 프로젝트에서 사용한 Double Stack Queue
기반의 Queue 두개의 요소를 더한 새로운 Queue를 반환하는 +
연산자를 중복 정의한다.
extension CalculatorItemQueue {
static func + (lhs: CalculatorItemQueue, rhs: CalculatorItemQueue) -> CalculatorItemQueue {
var result = CalculatorItemQueue()
let operatedResult = zip(lhs.statusQueue, rhs.statusQueue).map { $0 + $1 }
operatedResult.forEach { result.enqueue($0) }
return result
}
}
CalculatorItemQueue
에 대한 타임 메서드로 정의하며, 메서드 이름은 중복 정의한 연산자 +
와 일치한다. 덧셈은 이 큐의 핵심 동작이 아니기 때문에, 타입 메서드를 CalculatorItemQueue
구조체의 주 선언부 보다는 CalculatorItemQueue
의 익스텐션에 정의한다. 산술 덧셈 연산자가 이항 연산자이기 때문에, 이 연산자 메소드는 CalculatorItemQueue
타입의 입력 매개 변수는 두 개 취하고, 역시 CalculatorItemQueue
타입인, 단일 출력 값을 반환한다.var test1 = CalculatorItemQueue()
var test2 = CalculatorItemQueue()
for i in 1...10 {
test1.enqueue(Double(i))
test2.enqueue(Double(i + 1))
}
print((test1 + test2).statusQueue)
// [3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0, 21.0]
클래스와 구조체는 표준 단항 연산자 (unary operators) 도 구현할 수 있다. 단항 연산자는 단일 대상을 연산한다. 자신의 대상 앞에 (-a
처럼) 있으면 접두사 (prefix) 연산자이고 자신의 대상 뒤에 (b!
처럼) 있으면 접미사 (postfix) 연산자이다.
단항 접두사나 단항 접미사 연산자를 구현할 때는 연산자 메소드 선언의 func 키워드 앞에 prefix
나 postfix
수정자를 작성한다:
extension CalculatorItemQueue {
static prefix func - (queue: CalculatorItemQueue) -> CalculatorItemQueue {
var result = CalculatorItemQueue()
queue.myMap { -$0 }.forEach { result.enqueue($0) }
return result
}
}
myMap
은 기본 배열의 map
고차함수와 정확히 동일하게 연산되는 메서드이다.print((-test1).statusQueue)
// [-1.0, -2.0, -3.0, -4.0, -5.0, -6.0, -7.0, -8.0, -9.0, -10.0]
=
을 다른 연산과 조합한다. 예를 들어, 덧셈 할당 연산자 +=
는 덧셈과 할당을 단일 연산으로 조합한다. 복합 할당 연산자의 왼쪽 입력 매개 변수 타입은 inout
으로 표시하는데, 매개 변수 값을 연산자 메소드 안에서 직접 수정하기 때문이다.extension CalculatorItemQueue {
static func += (lhs: inout CalculatorItemQueue, rhs: CalculatorItemQueue) -> CalculatorItemQueue {
rhs.statusQueue.forEach { lhs.enqueue($0) }
return lhs
}
}
append
메서드와 비슷하게 적용되는 로직으로 예제를 작성했다.print((test1 += test2).statusQueue)
// [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0]
==
와 같지 않음 (not equal to) 연산자 !=
라는, 같음 비교 연산자 (euivalence operators) 를 구현하지 않는다. 대체로 ==
연산자는 구현하고, !=
연산자는 표준 라이브러리의 기본 구현을 써서 ==
연산자의 결과를 반대로 뒤집는다. ==
연산자 구현에는 두 가지 방법이 있는데: 스스로 구현할 수도, 또는 많은 타입들에서 스위프트에 통합 구현을 요청할 수도 있다. 두 경우 모두, 표준 라이브러리의 Equatable
프로토콜을 준수하도록 추가한다.extension CalculatorItemQueue {
static func == (lhs: CalculatorItemQueue, rhs: CalculatorItemQueue) -> Bool {
return lhs.statusQueue == rhs.statusQueue
}
}
==
연산자를 구현하여 배열의 그것과 정확히 동일하게 동작하도록 구현하였다.print(test1 == test2)
// false