1. 함수타입을 확장하면서 INVOKE()를 오버라이딩하는 예제
Kotlin Coroutines
코틀린 코루틴 라이브러리에서는 Continuation이라는 인터페이스가 있는데, 이 인터페이스는 비동기 작업의 결과를 처리하는 데 사용됩니다. Continuation 인터페이스는 resumeWith이라는 메서드를 가지고 있지만, 이를 invoke를 통해 간단하게 호출할 수 있습니다.
interface Continuation<T> {
fun resumeWith(result: Result<T>)
}
class PrintContinuation<T> : Continuation<T> {
override fun resumeWith(result: Result<T>) {
println(result.getOrNull())
}
}
fun main() {
val continuation = PrintContinuation<String>()
continuation.resumeWith(Result.success("Hello, Coroutines!")) // Output: Hello, Coroutines!
}
위 예제에서 Continuation 인터페이스를 구현한 PrintContinuation 클래스가 resumeWith 메서드를 오버라이딩하여 결과를 출력합니다. 이 예제를 invoke로 바꿔 보겠습니다.
interface Continuation<T> {
operator fun invoke(result: Result<T>)
}
class PrintContinuation<T> : Continuation<T> {
override fun invoke(result: Result<T>) {
println(result.getOrNull())
}
}
fun main() {
val continuation = PrintContinuation<String>()
continuation(Result.success("Hello, Coroutines!")) // Output: Hello, Coroutines!
}
invoke를 사용하면 resumeWith 대신 continuation(result) 형태로 호출할 수 있어 코드가 더 간결해집니다.
2. 그럼 굳이 함수가 아닌 클래스 + invoke 오버라이딩을 사용하는 이유
- 코드 간결성
invoke를 사용하면 함수 호출과 유사하게 객체를 사용할 수 있어 코드가 더 읽기 쉽고 간결해진다
- 함수형 프로그래밍 스타일
함수 객체를 함수처럼 사용할 수 있어 함수형 프로그래밍 스타일을 유지하면서 객체 지향 프로그래밍의 장점을 활용할 수 있다
- 캡슐화와 유연성
invoke를 오버라이딩하면 호출 방식의 캡슐화가 가능해지고, 다양한 호출 패턴을 유연하게 정의할 수 있습니다. 예를 들어, 추가적인 로직을 invoke 메서드에 포함시킬 수 있다
3. 멤버 확장
멤버 확장(Extension)은 코틀린의 강력한 기능 중 하나로, 기존 클래스에 새로운 메서드나 프로퍼티를 추가하는 기능을 의미합니다. 이를 통해 기존 클래스의 소스를 수정하지 않고도 클래스의 기능을 확장할 수 있습니다.
멤버 확장에는 크게 두 가지 유형이 있습니다:
- 함수 확장(Extension Functions)
- 프로퍼티 확장(Extension Properties)
함수 확장(Extension Functions)
함수 확장은 기존 클래스에 새로운 메서드를 추가하는 것을 의미합니다. 예를 들어, String 클래스에 새로운 메서드를 추가하고 싶을 때 사용합니다.
fun String.lastChar(): Char {
return this[this.length - 1]
}
fun main() {
val str = "Hello"
println(str.lastChar()) // Output: o
}
위 예제에서 String 클래스에 lastChar라는 확장 함수를 추가했습니다. 이제 String 객체에서 lastChar 메서드를 호출할 수 있습니다.
프로퍼티 확장(Extension Properties)
프로퍼티 확장은 기존 클래스에 새로운 프로퍼티를 추가하는 것을 의미합니다. 확장 프로퍼티는 실제로 상태를 저장하지 않으며, 게터(및 필요한 경우 세터)를 통해 값을 계산합니다.
val String.lastChar: Char
get() = this[this.length - 1]
fun main() {
val str = "Hello"
println(str.lastChar) // Output: o
}
위 예제에서 String 클래스에 lastChar라는 확장 프로퍼티를 추가했습니다. 이제 String 객체에서 lastChar 프로퍼티를 접근할 수 있습니다.
'독서' 카테고리의 다른 글
[이펙티브 코틀린] 2장. 가독성 (1) | 2024.06.30 |
---|---|
[이펙티브 코틀린] 1장. 안정성 (0) | 2024.06.23 |
[코틀린 인 액션] 10장. 애너테이션과 리플렉션 (0) | 2024.05.26 |
[코틀린 인 액션] 9장. 제네릭스 (0) | 2024.05.19 |
[코틀린 인 액션] 8장. 고차 함수: 파라미터와 반환 값으로 람다 사용 (0) | 2024.05.13 |