kotlinbeginner

SAM Conversions and Functional Interfaces

Use SAM conversions with fun interfaces: Java interop, event listeners, and callback patterns.

kotlin
// 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.