아이템 12 - 연산자 오버로드를 할 때는 의미에 맞게 사용하라

ds_chanin

·

2022. 3. 25. 22:27


연산자 오버로딩은 그 이름의 의미에 맞게 사용하자.

큰 힘에는 큰 책임이 따른다.

코틀린에서 ! 연산자는 boolean의 반대를 나타내는 not 연산을 의미한다. 이런 연산자를 팩토리얼을 표현하기 위해 아래와 같이 표현한다면 다음과 같다.

10 * !6

그리고 위 코드를 not으로 읽어보면 아래와 같이 된다.

10 *6.not()

오버로딩을 이런식으로 활용하면 혼란스럽고 오해의 소지가 있다.

코틀린의 모든 연산자는 별칭이다. 즉, 본래의 이름이 있기 때문에 그 의미를 벗어나도록 오버로딩하면 안된다.

분명하지 않은 경우

그런데 오버로딩을 한 연산자가 이름의 뜻을 제대로 의미하는지(관례를 충족하는지) 확신이 들지 않을 때가 있다.

아래의 경우 * 는 함수를 여러번 실행시키는 의미로 사용되었다.

3 * print("Hello!") // Hello!Hello!Hello!

그런데 딱 봤을때 3번 실행한다는 것인지 이어지는 함수의 반환 값에 3을 곱한다는 것인지 애매모호하다.

이렇게 의미가 명확하지 않은 경우 infix를 이용하여 확장 함수를 생성하여 사용하자.

operator fun Int.timesRepeated(operation: () -> Unit) = {
    repeat(this) { operation() }
}

3 timesRepeated { print("Hello!") }

규칙을 무시해도 되는 경우

앞서 설명한 오버로딩 규칙을 DSL(도메인 특화 언어)를 설계할 때는 무시해도 된다.

필자는 도메인 특화 언어는 그 언어 나름의 문법을 생성하는 것이라 무시해도 된다는 의미인것으로 해석했다.