Notice
Recent Posts
Recent Comments
Link
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Tags more
Archives
Today
Total
관리 메뉴

밤빵's 개발일지

[TIL]20241009 Extension Functions 본문

Kotlin

[TIL]20241009 Extension Functions

최밤빵 2024. 10. 9. 19:47

▶확장 함수란?

확장 함수는 기존 클래스에 새로운 함수를 추가하는 것처럼 보이지만, 실제로는 그 클래스를 확장하지 않고도 외부에서 정의할 수 있는 함수이다. 이러한 기능 덕분에 기존 라이브러리나 클래스를 수정하지 않고도 필요에 따라 유연하게 기능을 확장할 수 있다. 이는 특히 라이브러리외부 클래스를 직접 수정할 수 없을 때 유용하다. 확장 함수는 자바의 유틸리티 클래스와 비슷한 역할을 한다. 예를 들어, 자바에서는 StringUtils 같은 클래스에서 문자열 관련 메서드를 추가할 수 있지만, 코틀린에서는 해당 기능을 String 클래스에 직접 확장 함수로 추가하여 더욱 직관적인 코드를 작성할 수 있다.

 

▶확장 함수의 기본 사용법

확장 함수는 클래스 이름에 .을 붙여 마치 클래스의 멤버 메서드처럼 호출할 수 있지만, 실제로는 외부에 정의된 함수이다. 확장 함수는 일반 함수 선언과 매우 비슷하지만, 함수 이름 앞에 확장할 클래스 이름을 붙여야 한다.

fun String.addExclamation(): String {
    return this + "!"
}

 

 → String 클래스에 addExclamation이라는 확장 함수를 추가한 예시로, 이 함수는 문자열 끝에 !를 붙여서 반환한다. 이렇게 확장된 함수를 마치 String 클래스의 원래 메서드인 것처럼 사용할 수 있다.

 

val text = "Hello"
println(text.addExclamation())  // 출력: Hello!

→ 이 코드에서 text.addExclamation()을 호출하면, 문자열 Hello에 !가 추가되어 출력된다.

 

▶확장 함수와 멤버 함수의 우선순위

확장 함수는 기존 클래스에 직접 추가된 메서드처럼 보이지만, 실제로는 클래스 외부에서 정의된 함수이기 때문에 멤버 함수확장 함수가 동일한 이름을 가질 경우, 멤버 함수가 우선적으로 호출된다.

class MyClass {
    fun printMessage() {
        println("MyClass 메서드 호출!")
    }
}

fun MyClass.printMessage() {
    println("확장 함수 호출!")
}

val myClass = MyClass()
myClass.printMessage()  // 출력: MyClass 메서드 호출!

→ MyClass의 printMessage() 메서드가 정의되어 있지만, 동일한 이름의 확장 함수가 외부에 정의되어 있다. 이 경우, MyClass의 멤버 함수가 우선적으로 호출되며, 확장 함수는 호출되지 않는다.

 

▶null 가능 확장 함수

코틀린은 null 안전성을 기본으로 제공하고, 확장 함수도 null 가능 타입에 대해 확장할 수 있다. 이를 통해 null 가능 객체에서 안전하게 함수를 호출할 수 있다.

fun String?.isNullOrEmpty(): Boolean {
    return this == null || this.isEmpty()
}

val text: String? = null
println(text.isNullOrEmpty())  // 출력: true

→ 이 확장 함수는 null가능 타입인 String?에 대해 isNullOrEmpty라는 함수를 추가해서, 문자열이 null이거나 비어 있는지 여부를 확인하는 기능을 제공한다. 이렇게 null 가능 타입에 확장 함수를 적용하면, null 값을 안전하게 처리할 수 있다.

 

▶자주 사용되는 확장 함수 예시

 

▷문자열 조작

문자열을 다룰 때 확장 함수는 매우 유용하다. 예를 들어, 모든 문자열을 대문자로 변환하거나, 특정 패턴을 가진 문자열을 쉽게 조작할 수 있다.

fun String.shout(): String {
    return this.uppercase() + "!!!"
}

val message = "kotlin"
println(message.shout())  // 출력: KOTLIN!!!

 

▷리스트 조작

리스트 관련 확장 함수도 자주 사용된다. 예를 들어, 리스트의 모든 원소에 변환 작업을 적용하거나, 특정 조건에 맞는 원소를 필터링하는 작업을 간결하게 처리할 수 있다.

fun List<Int>.sumOddNumbers(): Int {
    return this.filter { it % 2 != 0 }.sum()
}

val numbers = listOf(1, 2, 3, 4, 5)
println(numbers.sumOddNumbers())  // 출력: 9 (1 + 3 + 5)

 

▶확장 함수의 장점

  • 기존 클래스 수정 불필요: 라이브러리나 외부 클래스 코드를 수정하지 않고도 기능을 확장할 수 있다.
  • 가독성 향상: 함수가 클래스의 일부처럼 동작하므로 코드 가독성이 높아진다.
  • 유연한 기능 확장: 특정 프로젝트에서만 필요한 기능을 확장 함수로 쉽게 추가하여 사용할 수 있다.

 

▶확장 함수의 단점

  • 멤버 함수와의 우선순위 문제: 확장 함수가 멤버 함수보다 우선순위가 낮기 때문에, 동일한 이름의 메서드가 있을 경우 혼란을 야기할 수 있다.
  • 내부 상태 접근 불가: 확장 함수는 해당 클래스의 비공개(private) 속성이나 메서드에는 접근할 수 없다. 오직 공개된(public) API만 사용할 수 있다.

확장 함수는 코틀린의 매우 유용한 기능으로, 기존 클래스에 새로운 기능을 추가하고 싶을 때 매우 유용하다.