728x90
이펙티브 코루틴을 요약한 내용입니다
- 연산자 오버로딩은 강력한 기능이지만 ‘큰 힘에는 큰 책임이 따른다’라는 말처럼 위험할 수 있음
- 연산자 오버로딩의 매력
fun Int.factorial(): Int = (1..this).product()
fun Iterable<Int>.product(): Int = fold(1) { acc, i -> acc * i }
- Int 확장 함수로 정의되어 있으므로, 편리하게 사용할 수 있음
print(10 * 6.factorial()) // 7200
- 연산자 오버로딩을 활용하면 !기호로 팩토리얼을 표현할수 있음
- 이렇게 사용하면 안됨
operator fun Int.not() = factorial() print(10 * !6) // 7200
- 함수의 이름이 not이므로 논리 연산에 사용해야지, 팩토리얼 연산에 사용하면 안됨
- 모든 연산자는 연산자 대신 함수로도 호출할 수 있음
- print(10 * 6.not()) // 7200
- 코틀린의 모든 연산자는 표와 같은 구체적인 이름을 가진 함수에 대한 별칭
- 각 연산자의 의미는 항상 같게 유지 됨
- 매우 중요한 설계 결정
분명하지 않은 경우
- 예를 들어 함수를 세 배 한다는 것은 무슨 의미?
- 함수를 세번 반복하는 새로운 함수를 생각 할 수 있음
operator fun Int.times(operation: () -> Unit): () -> Unit = { repeat(this) { operation() } } val tripledHello = 3 * { print("Hello") } tripledHello()
- 어떤 코드가 함수를 세 번 호출하는 것을 생각 할 수 있음
operator fun Int.times(operation: () -> Unit) { repeat(this) { operation() } } 3 * { print("Hello") }
- 의미가 명확하지 않다면, infix를 활용한 확장 함수를 사용하는 것이 좋음
infix fun Int.timesRepeated(operation: ()-> Unit) = {
repeat(this) { operation() }
}
val tripledHell = 3 timesRepeated { print("Hello") }
tripedHello()
- 톱레벨 함수(top-level function)를 사용하는 것도 좋음
- 함수를 n번 호출하는 것은 이미 stdlib에 구현되어 있음
repeat(3) { print("Hello") }
규칙을 무시해도 되는 경우
- 연산자 오버로딩 규칙을 무시해도 되는 중요한 경우가 있음
- 도메인 특화 언어(DSL)를 설계할 때
정리
- 연산자 오버로딩은 그 이름의 의미에 맞게 사용
- 연산자 의미가 명확하지 않다면, 연산자 오버로딩을 사용하지 않는 것이 좋음
- 이름이 있는 일반 함수를 사용 하는 것이 좋음
- 꼭 연산자 같은 형태로 사용하고 싶다면, infix 확장 함수 또는 톱레벨 함수를 활용
728x90
'코틀린 스터디 > 이펙티브 코틀린' 카테고리의 다른 글
아이템14) 변수 타입이 명확하지 않은 경우 확실하게 지정하라 (0) | 2024.03.19 |
---|---|
아이템13) Unit?을 리턴하지 말라 (0) | 2024.03.12 |
아이템11) 가독성을 목표로 설계하라 (0) | 2024.03.05 |
아이템10) 단위 테스트를 만들어라 (1) | 2024.02.29 |
아이템9) use를 사용하여 리소스를 닫아라 (0) | 2024.02.28 |