기존 자바 라이브러리와 코틀린 코드를 자연스럽게 통합하는 것은 코틀린의 핵심 목표 중 하나다.
코틀린은 확장 함수와 프로퍼티를 지원하여 기존 자바 API를 재작성하지 않고도 코틀린이 해당 기능을 사용할 수 있게 해준다.
확장 함수는 어떤 클래스의 멤버 메서드인 것처럼 호출할 수 있지만 그 클래스의 밖에 선언된 함수다. 확장 함수를 만들려면 추가하려는 함수 이름 앞에 그 함수가 확장할 클래스의 이름을 덧붙이기만 하면 된다.
클래스 이름 = 수신 객체 타입(receiver type)
확장 함수가 호출되는 대상이 되는 값(객체) = 수신 객체(receiver object)
fun String.midChar() = this.get(this.length / 2)
// 'String' = 객체 타입 'this' = 수신 객체
println("my text".midChar())
자바 클래스로 컴파일한 클래스 파일이 있는 한 그 클래스에 원하는 대로 확장을 추가할 수 있다. (Java, Kotlin, Groovy)
<aside> 💡 수신 객체의 프로퍼티와 메서드 사용
확장 함수 내부에서는 일반적인 인스턴스 메서드의 내부에서와 마찬가지로 수신 객체의 메서드나 프로퍼티를 바로 사용할 수 있다.
단, 클래스 안에서 정의한 메서드와 달리 확장 함수 안에서는 클래스 내부에서만 사용할 수 있는 private, protected 멤버를 사용할 수 없다.
</aside>
확장 함수는 어떻게 구현되는지 디컴파일 후, 자바 코드로 변환해보자.
// testFunction.kt
package testPackage
fun String.midChar() = this.get(this.length / 2)
// Decompile to Java
public final class TestFunctionKt {
public static final char midChar(@NotNull String $this$midChar) {
Intrinsics.checkNotNullParameter($this$midChar, "$this$midChar");
return $this$midChar.charAt($this$midChar.length() / 2);
}
}
확장 함수는 수신 객체의 외부에, 확장 함수가 선언된 파일 이름을 클래스 명으로 하는 클래스에 선언된다. 정적 메서드로 선언이 되고, 수신 객체를 첫번째 인자로 받는다.
⇒ 즉, 확장 함수는 단지 정적 메서드 호출에 대한 문법적인 편의일 뿐이다.
앞서 내부 구현 코드에서 엿보았듯이 새로운 클래스 안에 확장 함수가 선언되므로 일반적인 클래스 내부 메서드를 호출하는 것과 동일한 방법으로 호출할 수 있다.
char c = TestFunctionKt.midChar("Java");