코틀린 확장함수는 언제 사용해야할까?
이번 글에서는 코틀린 확장함수를 언제 사용하면 좋을지에 대해 알아봤다.
nextstep 미션을 수행하면서 다음과 같은 요구사항을 구현해야했다.
문자열(+, -, x, ÷)이 주어졌을 때, enum 으로 바꾸기
입력) +
결과) Operator.PLUS
먼저 "Operator"라는 이름으로 enum class를 선언해줬다.
enum class Operator(val symbol: String) {
PLUS("+"),
MINUS("-"),
MULTIPLY("x"),
DIVIDE("÷");
}
코틀린을 공부하면서 확장함수 개념에 대해 학습했고, 이번 기회에 사용해봤다.
다음은 문자열을 Operator로 변경해주는 로직이다.
fun String.findOperator(): Operator {
return Operator.values().firstOrNull { it.symbol == this }
이로써 다음과 같은 방법으로 "+" 문자열을 Operator.PLUS 로 변환할 수 있다.
"+".findOperator()
리뷰어님으로부터 확장함수를 사용한 이유에 대해 커멘트를 받았다.
확장함수를 사용하지 않는 보통의 상황이라면, findOperator()를 Operator enum class 내부에 정적인 함수로 선언했을 것이다.
흠... 궁금증이 생겼다. 🤔
일반적으로 어떤 상황에서 확장함수를 사용할까?
스택오버플로우에서 비슷한 질문을 찾아 내용을 정리해봤다.
1. 기존 API를 개선, 확장 또는 변경하려는 경우
확장 함수는 기존 클래스에 새로운 기능을 추가하는 관용적인 방법이다.
// 기존 API인 ObjectMapper를 확장
inline fun <reified T> ObjectMapper.readValue(src: ByteArray): T = readValue(src, jacksonTypeRef<T>())
2. 기존 메서드를 nullable에서 호출 가능하도록 확장하고 싶을 때
참고: kotlin docs
fun Any?.toString(): String {
if (this == null) return "null"
// After the null check, 'this' is autocast to a non-nullable type, so the toString() below
// resolves to the member function of the Any class
return toString()
}
3. 인터페이스에 inline default 함수를 추가하고 싶을 때 (인라인 함수는 final 함수여야 하므로, 확장함수를 사용해야 한다)
참고: injekt
interface InjektRegistry {
fun <T: Any> hasFactory(forType: TypeReference<T>): Boolean
}
inline fun <reified T: Any> InjektRegistry.hasFactory(): Boolean {
return hasFactory(fullType<T>())
}
참고
https://stackoverflow.com/questions/35317940/when-should-one-prefer-kotlin-extension-functions