[Kotlin] 확장 함수 / 확장 프로퍼티, 최상위 함수 / 최상위 프로퍼티
확장 함수 / 확장 프로퍼티
- Note ) 코틀린의 최상위 객체는 ``kt Any``이기 때문에, 여기에 추가하면 모든 객체에 확장 함수를 추가할 수 있다.
- 확장 함수를 사용하면 좋은 경우는
- String 같은 기본 타입을 확장하고 싶을 때. e.g., String.appendSignature (public으로 쓰는 경우도 많고, 시그니처를 사용하는 부분이 제한되어 있다면 private으로 만들면 아주 깔끔)
- 내가 만든 클래스라 마음대로 메서드 정의가 가능한 상황일지라도, 클래스에 포함하자니 무언가 애매한 기능일 때. (역시 보통은 사용처가 제한되는 경우가 많아서 private)
- 확장 함수를 사용해도 실행 시점에 부가 비용이 들지 않는다.
- 확장 함수가 클래스를 노출시키면 안되므로, 확장 함수의 가시성은 클래스의 가시성과 같거나 더 낮아야 한다.
확장 함수 ( extension function )
private fun String.appendSignature() =
"$this&signature=${HmacUtils(HmacAlgorithms.HMAC_SHA_256, secretKey).hmacHex(this)}"
확장 함수는 하위 클래스에서 오버라이드할 수 없다.
확장 함수는 클래스의 일부가 아니라, 클래스 밖에 선언되며 상속되지 않는다.
어떤 확장 함수를 호출할지는 수신 객체로 지정한 변수의 정적 타입에 의해 결정된다. ( 정적 디스패치, static dispatch )
확장 함수가 아닌 일반적인 메서드의 경우 상속 계층에서 오버라이드한 함수를 호출할 때 변수의 동적 타입에 의해 호출 함수가 결정되기 때문에 오버라이드한 함수가 호출된다. ( 동적 디스패치, dynamic dispatch )
```kt
open class View {
open fun click() = println("View normal method")
}
class Button: View() {
override fun click() = println("Button normal method")
}
fun View.extFunc() = println("View extFunc")
fun Button.extFunc() = println("Button extFunc")
>>> val view: View = Button() // View type 변수에 Button() 객체 할당
>>> view.click()
Button normal method // dynamic
>>> view.extFunc()
View extFunc // static
```
Note ) 내부적으로 확장 함수는 수신 객체를 첫 번째 인자로 받는 정적 메소드로 변환된다.
그래서 자바에서 확장 함수를 사용할 때는 이런 식으로 사용하게 되는데, 이를 생각해보면 왜 상속되지 않는지 이해가 된다.
```java
ExtensionsKt.extFunc(view)
```
확장 프로퍼티 ( extension property )
최상위 수준 함수 / 프로퍼티 (Top-Level Functions)
코틀린은 자바와 달리 최상위 수준에 함수나 프로퍼티를 정의할 수 있다.
JVM은 클래스 안에 들어있는 코드만 실행할 수 있기 때문에 최상위 수준 함수는 자동으로 파일 명을 클래스 명으로 하는 클래스에 들어가게 된다.
```java
// filename : join.kt를 java로 변환하면
package strings;
public class JoinKt {
public static string joinTostring(...) { ... }
}
```
최상위 함수가 포함되는 클래스 이름을 변경하고 싶다면
```kt
@file:JvmNanem("StringFunctions")
```
정적 유틸리티 클래스 vs 최상위 함수
- 정적 클래스는 한 클래스에 여러 유틸리티 메소드를 묶어 네임스페이스를 관리 할 수 있다는 장점이 있다. (kotlin에서는 companion object)
- 최상위 함수는 함수들에 대한 관리는 File 단위로 한다지만, 각각의 함수들이 global namespace를 사용하기 때문에 충돌을 조금 더 신경써야 한다.
- 실제로 사용 할 때는 class prefix 없이 함수만 명시해도 되는 최상위 함수가 더 깔끔한 경우가 많다.
'Java Stack > Kotlin' 카테고리의 다른 글
[Kotlin] enum / when / sealed (0) | 2017.12.01 |
---|---|
[Kotlin/Java] Inner Class / Nested Class (0) | 2017.12.01 |
[Regex] Kotlin (0) | 2017.12.01 |
[Kotlin] Tip2 + 문자열 템플릿 (0) | 2017.11.30 |
[Kotlin] Tip (0) | 2017.11.28 |