kotlinintermediate

Inline Functions and Reified Generics

Use inline functions with reified type parameters for type-safe operations without reflection.

kotlin
// Reified type parameters: access type info at runtime
inline fun <reified T> isType(value: Any): Boolean = value is T

inline fun <reified T> List<*>.filterIsType(): List<T> =
    filterIsInstance<T>()

inline fun <reified T> parseJson(jsonStr: String): T {
    // With reified, we can access T::class
    println("Parsing as ${T::class.simpleName}")
    // In real code: json.decodeFromString<T>(jsonStr)
    @Suppress("UNCHECKED_CAST")
    return when (T::class) {
        String::class -> jsonStr as T
        Int::class -> jsonStr.toInt() as T
        Double::class -> jsonStr.toDouble() as T
        else -> throw UnsupportedOperationException("Cannot parse ${T::class}")
    }
}

// Inline function for performance-critical lambdas
inline fun <T> measureTime(label: String, block: () -> T): T {
    val start = System.nanoTime()
    val result = block()
    val elapsed = (System.nanoTime() - start) / 1_000_000.0
    println("$label: ${elapsed}ms")
    return result
}

// crossinline: lambda can't return from outer function
inline fun transaction(crossinline block: () -> Unit) {
    println("BEGIN")
    try {
        block()
        println("COMMIT")
    } catch (e: Exception) {
        println("ROLLBACK: ${e.message}")
    }
}

// noinline: prevent inlining of specific lambda
inline fun runTasks(
    noinline errorHandler: (Exception) -> Unit,
    block: () -> Unit
) {
    try { block() } catch (e: Exception) { errorHandler(e) }
}

// Reified for service locator pattern
class ServiceLocator {
    private val services = mutableMapOf<String, Any>()

    inline fun <reified T : Any> register(service: T) {
        services[T::class.qualifiedName ?: T::class.simpleName!!] = service
    }

    inline fun <reified T : Any> resolve(): T {
        val key = T::class.qualifiedName ?: T::class.simpleName!!
        return services[key] as? T
            ?: throw IllegalStateException("Service not found: $key")
    }
}

interface Logger { fun log(msg: String) }
class ConsoleLogger : Logger {
    override fun log(msg: String) = println("[LOG] $msg")
}

fun main() {
    // Type checking
    println(isType<String>("hello"))  // true
    println(isType<Int>("hello"))     // false

    // Type filtering
    val mixed: List<Any> = listOf(1, "hello", 2.0, "world", 3)
    val strings = mixed.filterIsType<String>()
    val ints = mixed.filterIsType<Int>()
    println("Strings: $strings")
    println("Ints: $ints")

    // Reified parsing
    val num = parseJson<Int>("42")
    val text = parseJson<String>("hello")
    println("Num: $num, Text: $text")

    // Measure time
    val result = measureTime("computation") {
        (1..1_000_000).sum()
    }
    println("Result: $result")

    // Service locator
    val locator = ServiceLocator()
    locator.register<Logger>(ConsoleLogger())
    val logger = locator.resolve<Logger>()
    logger.log("Hello from service locator")
}

Use Cases

  • Type-safe operations without reflection overhead
  • Performance-critical higher-order functions
  • Service locator and dependency resolution

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.