kotlinbeginner
SAM Conversions and Functional Interfaces
Use SAM conversions with fun interfaces: Java interop, event listeners, and callback patterns.
kotlinPress ⌘/Ctrl + Shift + C to copy
// Kotlin functional interfaces (fun interface)
fun interface Converter<A, B> {
fun convert(from: A): B
}
fun interface Validator<T> {
fun validate(value: T): Boolean
}
fun interface Action {
fun execute()
}
fun interface Effect<T> {
fun run(value: T)
}
// Using SAM conversion
val intToString = Converter<Int, String> { "Number: $it" }
val isPositive = Validator<Int> { it > 0 }
val printAction = Action { println("Executed!") }
// Builder using fun interfaces
fun interface Specification<T> {
fun isSatisfiedBy(item: T): Boolean
// Default methods
fun and(other: Specification<T>) = Specification<T> {
this.isSatisfiedBy(it) && other.isSatisfiedBy(it)
}
fun or(other: Specification<T>) = Specification<T> {
this.isSatisfiedBy(it) || other.isSatisfiedBy(it)
}
fun not() = Specification<T> { !this.isSatisfiedBy(it) }
}
data class Product(val name: String, val price: Double, val category: String)
// Event system with SAM
fun interface EventHandler<T> {
fun handle(event: T)
}
class EventBus<T> {
private val handlers = mutableListOf<EventHandler<T>>()
fun on(handler: EventHandler<T>) { handlers.add(handler) }
fun emit(event: T) { handlers.forEach { it.handle(event) } }
}
// Middleware with SAM
fun interface Middleware<T> {
fun process(value: T, next: (T) -> T): T
}
fun <T> applyMiddleware(value: T, middlewares: List<Middleware<T>>): T {
fun chain(index: Int): (T) -> T = { v ->
if (index < middlewares.size) {
middlewares[index].process(v, chain(index + 1))
} else v
}
return chain(0)(value)
}
// Comparator-like fun interface
fun interface Ranking<T> {
fun rank(item: T): Int
}
fun main() {
// Basic SAM
println(intToString.convert(42))
println("Is 5 positive: ${isPositive.validate(5)}")
printAction.execute()
// Pass as lambda
fun <A, B> transform(value: A, converter: Converter<A, B>): B = converter.convert(value)
val result = transform(100) { "Value is $it" }
println(result)
// Specification pattern
val products = listOf(
Product("Laptop", 999.0, "electronics"),
Product("Mouse", 29.0, "electronics"),
Product("Book", 15.0, "books"),
Product("Keyboard", 79.0, "electronics")
)
val electronic = Specification<Product> { it.category == "electronics" }
val affordable = Specification<Product> { it.price < 100 }
val affordableElectronics = electronic.and(affordable)
println("\nAffordable electronics:")
products.filter { affordableElectronics.isSatisfiedBy(it) }
.forEach { println(" ${it.name}: \$${it.price}") }
// Event bus
println("\n--- Events ---")
val bus = EventBus<String>()
bus.on { println("Handler 1: $it") }
bus.on { println("Handler 2: ${it.uppercase()}") }
bus.emit("hello")
bus.emit("world")
// Middleware
println("\n--- Middleware ---")
val middlewares = listOf<Middleware<String>>(
Middleware { value, next -> next("[$value]") },
Middleware { value, next -> next(value.uppercase()) },
Middleware { value, next -> next("PREFIX-$value") }
)
println(applyMiddleware("hello", middlewares))
// Ranking
val ranking = Ranking<Product> { (it.price * 10).toInt() }
val ranked = products.sortedBy { ranking.rank(it) }
println("\nRanked: ${ranked.map { it.name }}")
}Use Cases
- Java interop with functional interfaces
- Event handling and callback patterns
- Specification and strategy patterns
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
kotlinbeginner
Null Safety — Elvis, Safe Call, and let
Master Kotlin null safety: safe calls, Elvis operator, let/also scoping, and smart casts.
Best for: Safe navigation through nullable chains
#kotlin#null-safety
kotlinbeginner
Data Classes — Copy, Destructure, and Equals
Use data classes for immutable models: auto-generated equals, hashCode, copy, and destructuring.
Best for: Immutable domain models and DTOs
#kotlin#data-class
kotlinbeginner
Extension Functions and Properties
Add methods to existing classes without inheritance: extension functions, properties, and generic extensions.
Best for: Adding utility methods to third-party types
#kotlin#extensions
kotlinbeginner
Scope Functions — let, run, apply, also, with
Master Kotlin scope functions: when to use let, run, apply, also, and with for concise code.
Best for: Object initialization and configuration
#kotlin#scope-functions