[Kotlin] Infix Function

KSang·2024년 5월 4일
0

TIL

목록 보기
96/101

Infix Function

컴포즈로 프로젝트를 구현 하다 보면 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 값을 반환한다.

0개의 댓글