어떤 클래스의 멤버 메소드인 것 처럼 호출 할 수 있지만 클래스 밖에 선언된 함수이다.
문자열의 마지막값을 돌려주는 함수
package strings
fun String.lastChar() : Char = this.get(this.length -1)
확장 함수를 만들려면 추가하는 함수 이름 앞에 그 함수가 확장할 클래스의 이름을 붙이면 된다.
클래스 이름을 수신객체 타입 이라 부르며 확장함수가 호출되는 대상을 수신 객체 라고 부른다.
fun String(수신객체 타입).lastChar: Char = this(수신객체).get(this(수신객체).length - 1)
println("Kotlin".lastChar()) //호출
>>n
수신 객체 멤버에 this 없이도 사용이 가능하다.
fun String.lastChar: Char = get(length - 1) //this 생략
- 일반적인 인스턴스 메소드의 내부에서와 마찬가지로 수신 객체의 메소드나 프로퍼티를 바로 사용 할 수 있다.
- 클래스 내부에서만 사용 할 수 있는 private 멤버나 protected 멤버를 사용 할 수 없다
외부 클래스에서 확장 함수 정의를 임포트를 통해 사용이 가능하다.
한 클래스 내에서 함수의 같은 이름이 충돌 하는 경우가 자주 생길 수 있는데, 임포트를 통해 개별 함수를 정할 수가 있다.
import string.lastChar
val c = "Kotlin".lastChar()
-- *를 사용한 임포트도 잘 작동한다.
import strings.*
val c = "Kotlin".lastChar()
--- as키워드를 통한 임포트한 클래스나 함수를 다른 이름으로 부를 수 있다.
import string.lastChar as last
val c = "Kotlin".last()
확장 함수는 수신객체를 첫 번째 인자로 받는 정적 메소드 이다. 때문에 코틀린의 파일명에 따라 자바의 클래스 이름이 선언되기 때문에 StringUtil.kt 파일에 정의 했다면 다음과 같이 호출 할 수 있다.
char c = StringUtilKt.lastChar("JAVA");
코틀린의 오버라이드도 객체지향의 오버라이드와 마찬가지로 코딩을 하면 된다.
---- 일반적인 멤버함수 오버라이드
open class View{
open fun click() = println("View clicked")
}
class Button:View(){
override fun click() = println("Button clicked")
}
val view:View = Button()
view.clicked()
>>Button clicked
fun View.showOff() = println("Im a View!")
fun Button.showOff() = println("Im a Button!")
val view:View = Button()
view.showOff()
>>Im a View!
위 코드에서는 view 변수가 Button 실제 객체 타입을 들고 있지만 이 경우 타입이 View이기 때문에 View의 확장 함수가 호출된다. 이유는 확장함수는 static한 정적 메소드로서 컴파일 시점때 미리 View 타입으로 결정하기 때문이다.
---확장 프로퍼티 선언
val String.lastChar:Char
get() = get(length -1 )
확장 함수의 경우와 마찬가지로 확장 프로퍼티도 일반적인 프로퍼티와 같은데, 뒷받침하는 필드가 없어서 기본 게터 구현을 제공 할 수 없으므로 최소한 게터는 꼭 정의를 해야한다.
---변경 가능한 확장 프로퍼티 선언
var StringBuilder.lastChar:Char
get() = get (length -1 )
set(value:Char){
this.setCharAt(length -1 , value)
}
println("Kotlin".lastChar)
>> n
val sb = StringBuilder("Kotlin?")
sb.lastChar = '!'
println(sb)
>> Kotlin!
확장 프로퍼티를 사용하는 방법은 멤버 프로퍼티를 사용하는 방법과 같다.
자바에서는 StringUtilKt(코틀린파일네임명).getLastChar("JAVA") 처럼 게터나 세터를 명시적으로 호출 해야한다.