[Kotlin] 클래스 안에 확장 함수?
Kotlin의 확장 함수는 보통 파일의 최상위 레벨에서 정의된다. 그런데 확장 함수를 클래스 안에서 정의할 수도 있다. 사실 어디서나 정의할 수 있다.
어쨌든, 클래스 안에 확장 함수를 정의하면 뭐가 좋을까?
확장 함수를 품은 클래스
클래스 ``A``에서 선언된 확장 함수는 ``A`` 내부 또는 ``A``를 receiver로 받는 람다식 안에서만 사용될 수 있다.
Receiver가 무엇인지 궁금하다면 다음 글을 참고하자.
다음 코드를 보자.
class Table {
fun <T> Column<T>.primaryKey(): Column<T>
fun Column<Int>.autoIncrement(): Column<T>
}
``Column<T>.primaryKey()`` 함수는 ``Column<T>``의 확장 함수이지만. ``Table`` 클래스 안에서 정의됐기 때문에 ``Table`` 안에서 또는 ``Table``을 receiver로 받는 람다식 안에서만 호출될 수 있다. 이렇게.
val someLambda: Table.() -> Unit = {
// receiver is Table
val id = Column<Int>().primaryKey().autoIncrement()
}
달리 말하면, ``Table``의 맥락 안에서만 호출할 수 있다는 뜻이다.
그래서요?
확장 함수를 특정 맥락 안에서만 사용할 수 있다는 점에 주목하자. 예를 들어 ``FileReader``에서는 ``File``을 쓸 수 없고 ``FileWriter``에서만 쓸 수만 있게 하고 싶다면, ``FileWriter`` 안에 ``File.write()``확장 함수를 구현하면 된다.
또 다른 예시로, Jetpack Compose UI에는 특정 범위(``BoxScope``, ``RowScope`` 등)에서만 사용할 수 있는 modifier가 있다. 이러한 modifier 역시 해당 scope 내부에 확장 함수로 정의되어 있다. 이처럼 확장 함수와 receiver를 잘 조합하면 깔끔하고 직관적인 DSL을 작성할 수 있다.
자신만의 DSL을 정의하고 싶은 사람이라면, Kotlin의 함수형 프로그래밍 기능을 숙지하자.