안녕하세요.
오늘은 SAM (Single Abstract Method) 과 invoke에 대해서 알아보겠습니다.
SAM과 invoke는 함수형 프로그래밍을 더 간결하고 쉽게 작성하기 위해 지원하는 기능입니다.
SAM (Single Abstract Method)
하나의 추상 메서드만 포함하는 인터페이스를 SAM 이라고 합니다
추상 메서드를 하나만 포함하는 클릭 리스너를 만들어 보겠습니다
interface OnClickListener {
fun onClick()
}
해당 인터페이스를 쓰는 예시입니다
val listener = object : OnClickListener {
override fun onClick() {
println("Clicked")
}
}
listener.onClick() // 출력: Clicked
SAM은 이 코드를 아래와 같이 사용할 수 있습니다
val listener = OnClickListener { println("Clicked") }
listener.onClick() // 출력: Clicked
그렇지만, 이는 에러 코드입니다.
추가 작업을 해줘야 합니다.
functional interface
함수형 인터페이스 입니다
코틀린에서 SAM 변환을 지원하기 위해선 fun interface 키워드를 사용해야 합니다
fun interface OnClickListener {
fun onClick()
}
val listener = OnClickListener { println("Clicked") }
listener.onClick() // 출력: Clicked
성공적으로 실행되는 것을 확인할 수 있습니다
invoke
invoke 기능을 활용하면
객체를 함수처럼 호출할 수 있습니다
class Greeter {
operator fun invoke(name: String) = "Hello, $name!"
}
fun main() {
val greeter = Greeter()
println(greeter("Kotlin")) // invoke를 사용하여 함수처럼 호출
}
사용 예제
1) SAM 활용 : 콜백 처리
SAM 변환은 주로 콜백 함수나 리스너 인터페이스를 간단하게 사용할 때 유용합니다
// 인터페이스 (예: 콜백용)
fun interface ResponseCallback {
fun onResponse(result: String)
}
// 네트워크 요청 함수 예시
fun performNetworkRequest(callback: ResponseCallback) {
// 네트워크 작업을 수행한 후 콜백 호출
callback.onResponse("Success")
}
fun main() {
// SAM 변환을 통해 콜백을 람다로 간단하게 구현
performNetworkRequest { result -> println("Network request completed with: $result") }
}
2) invoke 활용 : DSL 구현
DSL은 Domain Specific Language의 줄임말입니다
특정 도메인에 국한해 사용하는 언어입니다
class UserConfig {
var username: String = ""
var age: Int = 0
fun printConfig() {
println("UserConfig(username='$username', age=$age)")
}
}
class ConfigDSL {
private val userConfig = UserConfig()
// invoke를 통해 DSL을 실행할 수 있도록 설정
operator fun invoke(action: UserConfig.() -> Unit): UserConfig {
userConfig.action()
return userConfig
}
}
fun main() {
val config = ConfigDSL()
// DSL을 사용해 사용자 설정 정의
config {
username = "Alice"
age = 30
}.printConfig() // 출력: "UserConfig(username='Alice', age=30)"
}
3) SAM과 invoke의 결합 : 함수형 프로그래밍
SAM과 invoke를 함께 사용하면, 중간 처리 단계에서 사용되는 변환 로직을 설정할 때 유용합니다
// 단계별 데이터 처리 인터페이스
fun interface DataProcessor {
fun process(data: String): String
}
// 파이프라인을 구성하는 Processor 객체
class ProcessorPipeline {
private val processors = mutableListOf<DataProcessor>()
// invoke를 활용해 파이프라인 추가
operator fun invoke(processor: DataProcessor) {
processors += processor
}
fun execute(data: String): String {
return processors.fold(data) { acc, processor -> processor.process(acc) }
}
}
fun main() {
val pipeline = ProcessorPipeline()
// SAM 변환으로 데이터 처리 파이프라인 설정
pipeline { it.uppercase(Locale.getDefault()) }
pipeline { "$it!" }
// 파이프라인 실행
println(pipeline.execute("hello")) // 출력: "HELLO!"
}
'Kotlin' 카테고리의 다른 글
[Kotlin] DSL (Domain Specific Language) (0) | 2024.11.05 |
---|---|
[Kotlin] 함수형 프로그래밍 (2) | 2024.10.29 |
[Kotlin] Scope Function (2) | 2024.10.11 |
[Kotlin] Sealed Class (3) | 2024.09.22 |
[Kotlin] Extension Function (확장 함수) (0) | 2024.09.10 |