컴포즈로 프로젝트를 구현 하다 보면 CompositionLocalProvider를 쓸때가 있는데,
생긴게 독특하다.
CompositionLocalProvider(LocalDialogContentStyle provides DialogContentStyle)
X provides Y 이 부분이 평소에 보기 힘든 모습이라 그런지 코드를 들어가봤다.
@Stable
abstract class ProvidableCompositionLocal<T> internal constructor(defaultFactory: () -> T) :
CompositionLocal<T> (defaultFactory) {
/**
* Associates a [CompositionLocal] key to a value in a call to [CompositionLocalProvider].
*
* @see CompositionLocal
* @see ProvidableCompositionLocal
*/
infix fun provides(value: T) = ProvidedValue(this, value, true)
/**
* Associates a [CompositionLocal] key to a value in a call to [CompositionLocalProvider] if the key does not
* already have an associated value.
*
* @see CompositionLocal
* @see ProvidableCompositionLocal
*/
infix fun providesDefault(value: T) = ProvidedValue(this, value, false)
}
provides를 보면 infix fun으로 구현되어 있는데,
prvides의 앞에 있는 객체가 this 그 뒤에 있는 객체가 value라고 보면 된다.
이외에 infix fun의 가장 대표적인 사례는 Pair를 만들때 사용하는 to가 있다.
package kotlin
public infix fun <A, B> A.to(that: B): kotlin.Pair<A, B> { /* compiled code */ }
map같은걸 만들때 키-쌍으로 이루어진 Pair데이터를 넣기 위해 자주 사용하는 to가 infix function으로 구현되어 있다.
val ab = "a" to "b"
이유는 결국 코드의 가독성 때문이다.
일반적인 함수 호출보다 자연스러운 스타일의 코드를 작성할 수 있다.
또한 의도 또한 명확하게 표현할 수 있다.
예를 들면 a isLessThan b는 a < b인 명확한 의도를 자연어 처럼 전달할 수 있다.
코틀린 공식 코드 컨벤션
두 개의 객체에서 비슷한 역할을 하는 경우에만 함수를 인픽스로 선언하라고 한다.
좋은 예시로는 and, to, zip 이 있고 나쁜 예시로는 add가 있다.
수신자 객체를 변경 하는 경우 메서드를 인픽스로 선언하지 말라고한다예시
infix fun Int.and(other: Int): Int = this and other val result = 0b1101 and 0b1011 // 결과는 0b1001 infix fun <T, R> Iterable<T>.zip(other: Iterable<R>): List<Pair<T, R>> >= this.zip(other) val list1 = listOf(1, 2, 3) val list2 = listOf("a", "b", "c") val zipped = list1 zip list2 // [(1, 'a'), (2, 'b'), (3, 'c')]
컨벤션을 지켜서 infix function을 만들어보자
infix fun Int.within(range: Pair<Int, Int>): Boolean = this in range.first..range.second
// 사용 예:
val age = 25
val isAdult = age within (18 to 65) // true 반환
사용자가 입력한 숫자가 범위 안에 있는지 검사하는 function
여기선 사용자의 나이가 범위 안에 속하는지 확인하는 역할을 한다.
infix fun <T> T.isMemberOf(group: Collection<T>): Boolean = this in group
// 사용 예:
val person = "John"
val team = listOf("Alice", "Bob", "John")
val isInTeam = person isMemberOf team // true 반환
이 예제는 리스트 안에 객체가 있는지 확인하고 Boolean 값을 반환한다.