중급: 확장 함수
이 챕터에서는 코드를 더 간결하고 읽기 쉽게 만들어주는 특별한 Kotlin 함수를 살펴봅니다. 효율적인 디자인 패턴을 사용하여 프로젝트를 다음 단계로 발전시키는 방법을 배우세요.
확장 함수
소프트웨어 개발에서 원본 소스 코드를 변경하지 않고 프로그램의 동작을 수정해야 하는 경우가 종종 있습니다. 예를 들어, 프로젝트에서 서드파티 라이브러리의 클래스에 추가 기능을 더하고 싶을 수 있습니다.
확장 함수를 사용하면 클래스에 추가 기능을 확장할 수 있습니다. 확장 함수를 호출하는 방식은 클래스의 멤버 함수를 호출하는 방식과 동일합니다.
확장 함수의 완전한 구문을 소개하기 전에 리시버가 무엇인지 이해해야 합니다. 리시버는 함수가 호출되는 대상입니다. 다시 말해, 리시버는 정보가 공유되는 곳 또는 대상입니다.
이 예시에서 main()
함수는 리스트의 첫 번째 요소를 반환하기 위해 .first()
함수를 호출합니다. .first()
함수는 readOnlyShapes
변수 상에서 호출되므로, readOnlyShapes
변수가 리시버입니다.
확장 함수를 생성하려면 확장하려는 클래스의 이름 뒤에 .
과 함수의 이름을 작성합니다. 이어서 인자와 반환 타입을 포함한 나머지 함수 선언을 작성합니다.
예시:
fun String.bold(): String = "<b>$this</b>"
fun main() {
// "hello" is the receiver
println("hello".bold())
// <b>hello</b>
}
이 예시에서는 다음을 설명합니다:
String
은 확장된 클래스입니다.bold
는 확장 함수의 이름입니다..bold()
확장 함수의 반환 타입은String
입니다."hello"
, 즉String
의 인스턴스가 리시버입니다.- 리시버는 본문 내에서 키워드
this
로 접근됩니다. - 문자열 템플릿 (
$this
)은this
의 값에 접근하는 데 사용됩니다. .bold()
확장 함수는 문자열을 받아 굵은 글씨체(<b>
HTML 요소)로 반환합니다.
확장 지향 설계
확장 함수는 어디에든 정의할 수 있으며, 이를 통해 확장 지향 설계를 만들 수 있습니다. 이러한 설계는 핵심 기능을 유용하지만 필수적이지 않은 기능과 분리하여 코드를 더 쉽게 읽고 유지보수할 수 있도록 합니다.
좋은 예시는 네트워크 요청을 수행하는 데 도움이 되는 Ktor 라이브러리의 HttpClient
클래스입니다. 이 클래스의 핵심 기능은 단일 함수 request()
이며, 이 함수는 HTTP 요청에 필요한 모든 정보를 가져옵니다:
class HttpClient {
fun request(method: String, url: String, headers: Map<String, String>): HttpResponse {
// Network code
}
}
실제로 가장 많이 사용되는 HTTP 요청은 GET 또는 POST 요청입니다. 라이브러리에서 이러한 일반적인 사용 사례에 대해 더 짧은 이름을 제공하는 것이 합리적입니다. 그러나 이는 새로운 네트워크 코드를 작성할 필요 없이 특정 요청 호출만 있으면 됩니다. 즉, 별도의 .get()
및 .post()
확장 함수로 정의하기에 완벽한 후보입니다:
fun HttpClient.get(url: String): HttpResponse = request("GET", url, emptyMap())
fun HttpClient.post(url: String): HttpResponse = request("POST", url, emptyMap())
이 .get()
및 .post()
함수는 올바른 HTTP 메서드를 사용하여 request()
함수를 호출하므로 직접 호출할 필요가 없습니다. 이들은 코드를 간소화하고 이해하기 쉽게 만듭니다:
class HttpClient {
fun request(method: String, url: String, headers: Map<String, String>): HttpResponse {
println("Requesting $method to $url with headers: $headers")
return HttpResponse("Response from $url")
}
}
fun HttpClient.get(url: String): HttpResponse = request("GET", url, emptyMap())
fun main() {
val client = HttpClient()
// Making a GET request using request() directly
val getResponseWithMember = client.request("GET", "https://example.com", emptyMap())
// Making a GET request using the get() extension function
val getResponseWithExtension = client.get("https://example.com")
}
이 확장 지향 접근 방식은 Kotlin의 표준 라이브러리 및 다른 라이브러리에서 널리 사용됩니다. 예를 들어, String
클래스에는 문자열 작업을 돕는 많은 확장 함수가 있습니다.
확장 함수에 대한 자세한 내용은 확장을 참조하세요.
연습 문제
연습 1
정수를 받아 양수인지 확인하는 isPositive
라는 확장 함수를 작성하세요.
fun Int.// Write your code here
fun main() {
println(1.isPositive())
// true
}
예시 솔루션
fun Int.isPositive(): Boolean = this > 0
fun main() {
println(1.isPositive())
// true
}
연습 2
문자열을 받아 소문자 버전을 반환하는 toLowercaseString
라는 확장 함수를 작성하세요.
힌트
String
타입에 .lowercase()
함수를 사용하세요. fun // Write your code here
fun main() {
println("Hello World!".toLowercaseString())
// hello world!
}
예시 솔루션
fun String.toLowercaseString(): String = this.lowercase()
fun main() {
println("Hello World!".toLowercaseString())
// hello world!
}