본문 바로가기
Android.Kotlin

[Kotlin] extension 함수의 이해

by 동동하다 2023. 10. 31.
반응형

코틀린에서 extension 함수는 기존에 존재하는 클래스의 변형 없이 새로운 함수를 추가할 수 있도록 해준다. 이 것은 기존에 정의되어 있지 않더라도 정의되어 있는 것처럼 사용 할 수 있도록 하여 좀 더 코틀린을 유연하게 사용할 수 있도록 도와준다. 

예를 들어 우리가 컨트롤 할 수 없는 3rd party library의 클래스에 필요한 메서드를 추가할 수 있다.

장점

  • 클래스 소스파일의 수정 없이 함수를 추가할 수 있다. 소스 코드가 없는 경우 매우 유용하게 사용될 수 있다.
  • 관련된 함수를 하나의 클래스나 오브젝트로 그룹핑 할 수 있어 가독성 있고 이해하기 쉬운 코드를 작성할 수 있게 해 준다.
  • 코드의 중복을 줄여서 유지보수에 유용하다.

단점

많은 장점에도 불구하고 extension 도 몇 가지 단점이 존재한다.

  • 코틀린 문법이 익숙하지 않은 경우 이해하는 어려울 수 있다.
  • 네이밍 충돌 이슈가 존재한다. 특히 멀티의 extension 이 같은 이름, 비슷한 타입의 파마리터를 가질 때 충돌이 발생한다

예시

예시를 한번 보자

fun Int.isEven(): Boolean {
    return this % 2 == 0
}

위 예시에서 Int 클래스에 isEven이라는 extention 함수를 정의 하였다. 확장 대상인 receiver 는 Int 형 이고 반환되는 값은 Boolean 타입이 된다.

 

위 예시의 결과는 다음과 같다.

val number = 10
val isNumberEven = number.isEven()
println(isNumberEven) // true

isEven 이라는 함수는 내부적으로 선언되지 않았지만 Int 클래스의 한 함수 형태로 호출된다.

정적 처리

extension 은 실제로 클래스의 확장이 아니다. extension의 정의에서 보면 멤버 변수 및 메서드를 해당 클래스에 추가하지 않는다. 다만 해당 타입의 변수에 dot 기반으로 호출 가능한 함수를 생성한다. 정적으로 처리되기에 extension 함수는 컴파일 시점에 리시버 타입이 결정된다. 

open class Shape
class Rectangle: Shape()

fun Shape.getName() = "Shape"
fun Rectangle.getName() = "Rectangle"

fun printClassName(s: Shape) {
    println(s.getName())
}

printClassName(Rectangle())

위의 예시에서 "Shape"가 출력된다. 일반적인 경우는 "Rectangle" 이 호출되겠지만 extension의 경우 선언 시 타입의 영향을 받기 때문이다

프로퍼티 확장

extension을 통해 함수를 확장할 수 있다면 프로퍼티도 확장할 수 있을까?

결론부터 말하면 가능하다. extension 은 정적으로 코드를 생성하므로 실제 저장할 필드를 생성하지는 않지만 getter/setter의 형태로 확장이 가능하다

결론

extension 함수는 코틀린을 좀 더 퀄리티 있고 유연한 코딩을 할 수 있도록 도와준다. 코틀린뿐만 아니라 다른 몇몇 언어에서도 extension 기능을 제공하고 있기에 extension의 개념을 이해하고 언제 사용할 수 있을지를 고민해 두면 많은 도움이 된다. 

반응형