어떤 클래스의 멤버 메소드인 것처럼 호출할 수 있지만 그 클래스의 밖에 선언된 함수이다.
fun String.lastChar(): Char = this.get(this.length-1)
// this 생략 가능
fun String.lastChar(): Char = get(length-1)
>>> println("abc".lastChar()) // "abc"는 수신 객체, String은 수신 객체 타입
c
수신 객체 타입 (receiver type)
: 확장이 정의될 클래스수신 객체 (receiver object)
: 그 클래스에 속한 인스턴스 객체 캡슐화
를 깨진 않는다private
이나 protected
로 선언된 멤버는 사용할 수 없다.as
키워드를 사용하면 import한 클래스나 함수를 다른 이름으로 부를 수 있다. (다른 여러 패키지에 속해있는 이름이 같은 함수를 가져와 사용해야 하는 경우 충돌 방지)import strings.lastChar as last
val c = "Kotlin".last()
자바에서 확장 함수 호출
- 내부적으로 확장 함수는
수신 객체
를 첫 번째 인자로 받는 정적 메소드(static method)이다. 그래서 확장 함수를 호출해도 부가 비용이 들지 않는다.- static method를 호출하면서 첫 번째 인자로
수신 객체
를 넘기기만 하면 된다./* 자바 */ // 확장 함수를 StringUtil.kt파일에 정의 char c = StringUtilKt.lastChar("Java");
fun <T> Collection<T>.joinToString(
separator: String = ", ",
prefix: String = "",
postfix: String = ""
): String {
val result = StringBuilder(prefix)
for ((index, element) in this.withIndex()) {
if (index > 0) result.append(separator)
result.append(element)
}
result.append(postfix)
return result.toString()
}
>>> val list = arrayListOf(1, 2, 3)
>>> println(list.joinToString(" ")
1 2 3
// 구체적인 타입을 수신 객체 타입으로 지정할 수도 있다.
fun Collection<String>.join(
separator: String = ", ",
prefix: String = "",
postfix: String = ""
) = joinToString(separator, prefix, postfix)
>>> println(listOf("one", "two", "eight").join(" "))
one two eight
Method Dispatch : 어떤 메소드를 호출할지 결정해서 실행시키는 과정
- Static Dispatch: 컴파일 시점에서 컴파일러가 특정 메소드를 호출할 것이라고 명확히 알고 있는 경우이다.
- Dynamic Dispatch: 컴파일러가 어떤 메소드를 호출할 지 모르는 경우이다. 호출할 메소드를 런타임 시점에 결정한다.
open class View{
open fun click() = println("View Clicked")
}
class Button: View(){
override fun click() = println("Button Clicked")
}
>>> val view: View = Button()
>>> view.click()
Button Clicked
static
하게 결정하기 때문에 오버라이드 할 수 없다.fun View.showOff() = println("I'm a view!")
fun Button.showOff() = println("I'm a button!")
>>> val view: View = Button()
>>> view.showOff()
I'm a view!
getter
는 필수적으로 정의 해야 한다.val String.lastChar: Char
get() = get(length-1)
var StringBuilder.lastChar: Char
get() = get(length-1)
set(value: Char){
this.setCharAt(length-1, value)
}