일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 조합
- BFS
- 자바
- 스카이라인 쉬운거
- 2501
- 프로그래머스
- 완전탐색
- 백준
- BuildConfig
- Android
- 백준 14501
- SWEA
- hilt
- java
- 순수함수
- 순열
- 백준 퇴사
- val
- 오르막수
- EditorInfo
- Parcelize
- 약수 구하기
- dfs
- 최단경로
- 시뮬레이션
- EditText
- 지능형 기차2
- imeOptions
- Parcelable
- Kotlin
- Today
- Total
안드 공부를 해볼까?
[확장함수] 코틀린 확장함수와 확장 프로퍼티 본문
2022.09.27 - [문법/Kotlin] - [확장함수] 코틀린 함수로 호출하기 쉽게 만들기
이전 포스팅에서 계속됩니다.
확장함수는 같은 클래스의 멤버 메서드인 것 처럼 호출할 수 있는 함수를 말합니다.
사용방법은 확장하고자 하는 함수 앞에 클래스의 이름을 작성해주면 됩니다.
fun String.lastChar() : Char = this.get(this.length -1)
//same function
fun String.lastChar() : Char = get(length - 1)
println("test".lastChar())
>>> t
함수 앞에 있는 클래스는 수신 객체의 타입, this는 수신 받은 객체가 됩니다.
“test”.lastChar()의 예시에서 앞의 String은 “test”의 객체, this는 “test”가 가지고 있는 객체입니다.
위의 this는 생략이 가능합니다.
하지만 객체를 수신한다고 해서 캡슐화가 깨지지는 않습니다.
예를 들면 **객체 클래스 내부에서만 사용가능한 멤버(private, protected)**들은 사용할 수 없습니다.
3.3.1 임포트와 확장 함수
우리가 확장 함수를 사용할 땐 반드시 import를 해줘야 합니다.
코틀린은 이런 확장함수 import 형식을 다양하게 바꿀 수 있습니다.
/* 기존과 동일한 import */
import strings.lastChar;
val c = "test".lastChar()
/* 전체를 포함하는 import */
import strings.*;
val c = "test".lastChar()
/* 커스텀 import */
import strings.lastChar as last
val c = "test".last()
마지막 커스텀 import는 이름이 같은 함수를 가져올 때 충돌을 방지할 수 있습니다.
일반적인 클래스나 함수라면 전체 이름을 쓰지만 코틀린에서 확장함수는 반드시 짧게 써야합니다.
3.3.2 자바에서 확장 함수 호출
자바에서도 코틀린의 확장함수 기능이 사용가능합니다. 앞서 본 확장함수의 생성방법으로 말이죠.
/* StringUtil.kt */
fun String.lastChar() = get(lenght - 1)
/* 변환된 StringUtilKt.java */
public class StringUtilKt {
public static String lastChar(...){ ... }
}
/* 자바에서 사용 */
char c = StringUtilKt.lastChar("java");
3.3.3 확장 함수로 유틸리티 함수 정의
앞서 본 joinToString을 이제 최종 버전을 만들어봅시다. 마치 코틀린 라이브러리에서 제공하는 것 처럼 말이죠.
fun 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()
}
//use joinToString
val list = listOf(1,2,3)
println(list.joinToString(separator = "; ", prefix = "{", postfix = "}"))
>>> {1; 2; 3}
val arrayList = arrayListOf(1,2,3)
println(arrayList.joinToString(" "))
>>> 1 2 3
또한 제네릭이 아닌, 특정 자료형으로 받고 싶다면 커스텀이 가능합니다.
fun Collection<String>.join(
separator: String = ", ",
prefix: String = "",
postfix: String = ""
) = joinToString(separator, prefix, postfix)
//error: type dismatch
val list = listOf(1,2,3)
println(list.join())
3.3.4 확장 함수는 오버라이드할 수 없다.
확장 함수가 자바에서 변환될 때 정적 메서드로 변환되는 것을 확인했습니다.
그 전에 기본적인 오버라이드 메서드를 한번 보겠습니다.
open class View{
open fun onClick() = "view click"
}
class Button : View(){
override fun onClick() = "button click"
}
val view : View = Button()
println(view.onClick())
>>> button click
View에 선언된 onClick을 재정의하여 Button에도 사용하도록 했습니다.
자바에서도 알 수 있는 것 처럼 부모 클래스 형식은 자식 클래스로 초기화가 가능합니다. 사용되는 건 자식 클래스의 멤버 메서드지만요.
하지만 확장함수는 클래스 외부에 선언 되기 때문에 재정의가 되지 않습니다.
fun View.showOff() = "view"
fun Button.showOff() = "button"
val view : View = Button()
println(view.showOff())
>>> view
위의 경우를 보면 view가 Button으로 초기화 됐음에도 view가 나오게 됩니다. 확장함수는 클래스 외부에 있으며 정적 메서드 이기 때문이죠.
3.3.5 확장 프로퍼티
코틀린은 프로퍼티 또한 확장할 수 있습니다.
fun String.lastChar() : Char = get(length - 1)
//프로퍼티 확장
val String.lastChar: Char
get() = get(length - 1)
//확장 프로퍼티 사용
println("test".lastChar)
>>> t
안드로이드 개발을 하며 get과 set이 자동으로 되는 경우를 많이 봤을겁니다.
그것 또한 확장 프로퍼티를 사용했을 겁니다. 하지만 무조건 get, set이 가능하지는 않습니다.
위의 lastChar는 set을 통해 해줄 수 있는게 있을까요? this로 가져오는 건 마지막 단어 1개가 되는데 set을 해줄만한 것이 없을겁니다.
var StringBuilder.lastChar : Char
get() = get(length - 1)
set(value) {this.append(value)}
val builder = StringBuilder("test")
builder.lastChar = '1'
println(builder.toString())
>>> test1
오히려 StringBuilder를 통해 맨 뒤에 1개를 붙이면 더 좋은 방법이겠네요.
이 처럼 get과 set을 통해 더 쉽게 확장함수를 사용합니다.
'문법 > Kotlin' 카테고리의 다른 글
[Kotlin] 클래스와 프로퍼티 (0) | 2022.12.21 |
---|---|
[Kotlin] 코틀린 함수와 변수 (0) | 2022.12.16 |
[Kotlin] 순수함수 (0) | 2022.12.15 |
[확장함수] 코틀린 함수로 호출하기 쉽게 만들기 (0) | 2022.09.27 |
[Kotlin] 코틀린에서 컬렉션 만들기 (0) | 2022.09.27 |