kotlinbeginner
Companion Objects — Static-Like Members and Factories
Use companion objects for factory methods, constants, and implementing interfaces at the class level.
kotlinPress ⌘/Ctrl + Shift + C to copy
import java.time.Instant
import java.util.UUID
interface JsonSerializable {
fun toJson(): String
}
// Companion object acts as a factory
data class User private constructor(
val id: String,
val name: String,
val email: String,
val createdAt: Instant
) : JsonSerializable {
companion object {
// Constants
const val MAX_NAME_LENGTH = 50
val DEFAULT_DOMAIN = "example.com"
// Factory methods
fun create(name: String, email: String): User {
require(name.length <= MAX_NAME_LENGTH) { "Name too long" }
require(email.contains("@")) { "Invalid email" }
return User(UUID.randomUUID().toString(), name, email, Instant.now())
}
fun fromCsv(csv: String): User {
val parts = csv.split(",").map { it.trim() }
require(parts.size >= 2) { "CSV must have name and email" }
return create(parts[0], parts[1])
}
fun guest(): User = create("Guest", "guest@$DEFAULT_DOMAIN")
}
override fun toJson(): String =
"""{ "id": "$id", "name": "$name", "email": "$email" }"""
}
// Companion implementing interface
interface Factory<T> {
fun create(): T
}
class Connection private constructor(val url: String) {
companion object : Factory<Connection> {
override fun create(): Connection = Connection("default://localhost")
fun create(url: String): Connection = Connection(url)
}
}
// Named companion
class Logger {
companion object Config {
var level: String = "INFO"
var format: String = "[%s] %s"
fun configure(level: String, format: String) {
this.level = level
this.format = format
}
}
fun log(message: String) {
if (shouldLog()) println(Config.format.format(Config.level, message))
}
private fun shouldLog() = true
}
fun main() {
// Factory methods
val user = User.create("Alice", "alice@test.com")
println(user)
println(user.toJson())
val guest = User.guest()
println("Guest: $guest")
val fromCsv = User.fromCsv("Bob, bob@test.com")
println("From CSV: $fromCsv")
// Constants
println("Max name: ${User.MAX_NAME_LENGTH}")
// Companion implementing interface
val conn = Connection.create("jdbc://db:5432")
println("Connection: ${conn.url}")
// Named companion
Logger.Config.configure("DEBUG", "[%s] → %s")
Logger().log("Hello!")
// Extension on companion
println(User.fromCsv("Charlie, charlie@test.com"))
}Use Cases
- Factory methods with validated construction
- Class-level constants and configuration
- Static-like interface implementations
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
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
kotlinbeginner
Collections — map, filter, groupBy, and More
Master Kotlin collections: functional transformations, aggregations, grouping, and partition operations.
Best for: Data processing and transformation pipelines
#kotlin#collections