-
12장 - 연산자 오버로드 할 때는 의미에 맞게 사용하라Kotlin/Effective Kotlin 요약 2023. 2. 10. 00:01728x90
팩토리얼을 구하는 함수
fun main() { print(6.factorial()) } fun Int.factorial(): Int = (1..this).product() fun Iterable<Int>.product(): Int = fold(1) {acc, i -> acc * i} //출력결과 : 720
팩토리얼은 다음과 같이 ! 기호를 사용해 표기하는 것을 우리는 알고 있습니다.
코틀린은 이런 연산자를 지원하지 않지만 다음과 같이 연산자 오버로딩을 활용하면 만들어낼 수 있습니다.
fun main() { print(!6) print(6.not()) } operator fun Int.not() = factorial() fun Int.factorial(): Int = (1..this).product() fun Iterable<Int>.product(): Int = fold(1) {acc, i -> acc * i}
이제 !기호로 팩토리얼을 표현할 수 있습니다.
이렇게 해도 될까요? 안됩니다.
이 함수의 이름은 not이며 논리 연산에 사용해야지 팩토리얼 연산에 사용하면 안 됩니다.
코드를 이렇게 작성하면 굉장히 혼란스럽고 오해의 소지가 있습니다.
6.not() 과 같은 코드는 어떻게 보이시나요?
분명하지 않은 경우
fun main() { val tripledHello = 3 * {print("Hello")} tripledHello() } operator fun Int.times(operation: () -> Unit): () -> Unit = { repeat(this) {operation()} }
다음과 같은 코드가 함수를 세 번 호출한다는 것을 쉽게 이해할 수 있을 수 있습니다.
하지만 의미가 명확하지 않다면 infix를 활용한 확장 함수를 사용하는 것이 좋습니다.
infix는 중위 함수입니다.
하지만 사실 함수를 n번 호출하는 것은 다음과 같은 형태로 이미 stdlib에 구현되어 있습니다.
repeat(3){println("Hello")}
규칙을 무시해도 되는 경우
DSL을 사용하는 경우에는 규칙을 무시해도 됩니다.
고전적인 HTML DSL
body{ div{ + " Some text" } }
String.unaryPlus가 사용됐지만 상관없습니다.
결론
연산자 오버로딩은 의미가 명확하면 사용하지 않는 것이 좋습니다.
대신 infix 확장 함수 또는 톱레벨 함수를 활용하세요
728x90'Kotlin > Effective Kotlin 요약' 카테고리의 다른 글
14장 - 변수 타입이 명확하지 않은 경우 확실하게 지정하라 (0) 2023.02.12 13장 - Unit?을 리턴하지 말라 (0) 2023.02.11 11장 - 가독성을 목표로 설계하라 (0) 2023.02.09 10장 - 단위 테스트를 만들어라 (0) 2023.01.26 9장 - use를 사용하여 리소스를 닫아라 (0) 2023.01.25