kotlinbeginner
Extension Functions and Properties
Add methods to existing classes without inheritance: extension functions, properties, and generic extensions.
kotlinPress ⌘/Ctrl + Shift + C to copy
// String extensions
fun String.isEmail(): Boolean =
matches(Regex("^[\\w.+-]+@[\\w-]+\\.[\\w.-]+$"))
fun String.truncate(maxLength: Int, suffix: String = "..."): String =
if (length <= maxLength) this
else take(maxLength - suffix.length) + suffix
fun String.toSlug(): String =
lowercase()
.replace(Regex("[^a-z0-9\\s-]"), "")
.replace(Regex("\\s+"), "-")
.trim('-')
// List extensions
fun <T> List<T>.secondOrNull(): T? = if (size >= 2) this[1] else null
fun <T> List<T>.chunkedWithOverlap(size: Int, overlap: Int): List<List<T>> {
require(overlap < size) { "Overlap must be less than chunk size" }
val step = size - overlap
return (0..this.size - size step step).map { i ->
subList(i, (i + size).coerceAtMost(this.size))
}
}
// Extension property
val String.wordCount: Int
get() = trim().split(Regex("\\s+")).filter { it.isNotBlank() }.size
// Generic extension
fun <T : Comparable<T>> T.clamp(min: T, max: T): T = when {
this < min -> min
this > max -> max
else -> this
}
// Nullable extensions
fun String?.orEmpty(): String = this ?: ""
fun <T> List<T>?.orEmpty(): List<T> = this ?: emptyList()
// Extension on companion (requires companion)
data class User(val name: String, val email: String) {
companion object
}
fun User.Companion.fromCsv(csv: String): User {
val (name, email) = csv.split(",").map { it.trim() }
return User(name, email)
}
// Scope function patterns with extensions
fun <T> T.applyIf(condition: Boolean, block: T.() -> T): T =
if (condition) block() else this
fun main() {
// String extensions
println("test@email.com".isEmail()) // true
println("Hello World!".truncate(8)) // Hello...
println("My Blog Post Title".toSlug()) // my-blog-post-title
println("Hello world foo".wordCount) // 3
// List extensions
println(listOf(1, 2, 3).secondOrNull()) // 2
println(listOf(1, 2, 3, 4, 5).chunkedWithOverlap(3, 1))
// [[1, 2, 3], [3, 4, 5]]
// Clamp
println(150.clamp(0, 100)) // 100
println(3.14.clamp(0.0, 1.0)) // 1.0
// Companion extension
val user = User.fromCsv("Alice, alice@test.com")
println(user)
// Conditional apply
val query = "SELECT *"
.applyIf(true) { "$this WHERE active = true" }
.applyIf(false) { "$this ORDER BY name" }
println(query)
}Use Cases
- Adding utility methods to third-party types
- Domain-specific language construction
- Clean API design without utility classes
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
kotlinadvanced
Type-Safe DSL Builder
Build domain-specific languages with Kotlin: receiver lambdas, @DslMarker, and nested builders.
Best for: Configuration DSLs for frameworks
#kotlin#dsl
kotlinbeginner
File I/O — Read, Write, and Process
Read and write files in Kotlin: readText, useLines, buffered I/O, and file tree walking.
Best for: Configuration file reading and writing
#kotlin#file-io
kotlinintermediate
Extension Properties and Receiver Functions
Add properties and functions to existing classes: extension receivers, generic extensions, and DSL patterns.
Best for: Adding utility methods to existing types
#kotlin#extensions
kotlinbeginner
String Processing Utilities
Common string operations in Kotlin: split, join, pad, replace, regex, and template processing.
Best for: CSV and delimited data parsing
#kotlin#strings