Kotlin 고유의 기능과 패러다임을 최대한 활용하여, 간결하고 읽기 쉽고 안정적이며 유지보수하기 좋도록 코드를 작성하는 팁을 정리합니다.
val name = "황용호"data class User(val id: Int, val name: String)let, apply, run, also, with 같은 스코프 함수들을 사용하여 객체 초기화나 null 체크를 간결하게 작성할 수 있습니다.
이러한 함수들을 활용하면 불필요한 임시 변수 선언 없이 연산을 체인으로 구성할 수 있습니다.
// 예시: null 안전한 객체 활용
val length = name?.let { it.length } ?: 0
// 예시: 객체 초기화 후 self 반환 (빌더 패턴 효과)
class User(val no: Int) {
lateinit var name: String
}
fun getUser(no: Int) = User(no).apply {
name = "황용호"
}
fun main() {
val user = getUser(10)
println(user.no)
println(user.name)
}
kotlin에서는 함수를 값으로 다루고, 인자로 전달하거나 반환할 수 있습니다.
람다식을 이용하면 함수형 프로그래밍 스타일로 코딩할 수 있습니다.
fun operateOnNumbers(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
return operation(a, b)
}
fun main() {
fun add(x: Int, y: Int): Int {
return x + y
}
fun subtract(x: Int, y: Int): Int {
return x - y
}
println(operateOnNumbers(5, 3, ::add)) // 8
println(operateOnNumbers(5, 3, ::subtract)) // 2
println(operateOnNumbers(5, 3) { x, y -> x * y }) // 15
}
map, filter, reduce, forEach 등 함수형 연산을 활용하여 컬렉션을 간결하게 처리합니다.val numbers = listOf(1, 2, 3, 4, 5)
val evenNumbers = numbers.filter { it % 2 == 0 }?.)와 엘비스 연산자(?:)를 활용하여 null 값에 안전하게 접근합니다.val result = someNullableValue?.someMethod() ?: defaultValue!!)는 사용을 최소화합니다.fun String.isEmailValid(): Boolean {
return this.contains("@")
}
// 사용 예:
val email = "jogakdal@gmail.com"
println(email.isEmailValid())// 문자열이 숫자로만 이루어졌는지 검사
val String.isDigit: Boolean
get() = this.all { it.isDigit() }by lazy를 사용하여 val 프로퍼티를 처음 접근 시 초기화합니다.
val heavyComputationResult: String by lazy {
println("실제 연산을 수행합니다.")
"계산 결과"
}
fun main() {
println("프로그램 시작")
println("중간 작업")
println("결과: $heavyComputationResult")
println("다시 결과: $heavyComputationResult")
}
lateinit는 var 프로퍼티의 초기화를 늦출 때 사용합니다.
class MyClass {
lateinit var message: String
fun initializeMessage() {
message = "Hello, Kotlin!"
}
fun printMessage() {
if (::message.isInitialized) println(message)
else println("message 변수는 아직 초기화되지 않았습니다.")
}
}
fun main() {
val myObject = MyClass()
myObject.printMessage() // 출력: message 변수는 아직 초기화되지 않았습니다.
myObject.initializeMessage()
myObject.printMessage() // 출력: Hello, Kotlin!
}
또한, Sequence를 활용하여 컬렉션의 연산을 지연 평가 방식으로 처리할 수 있습니다.
fun main() {
println("using collection")
// 총 205번 연산
(100..200).map {
println("doubling $it")
it * 2
}.filter {
println("filtering $it")
it % 3 == 0
}.first()
println("using sequence")
// 총 6번 연산
(100..200).asSequence().map {
println("doubling $it")
it * 2
}.filter {
println("filtering $it")
it % 3 == 0
}.first()
}
when 표현식을 활용하여 조건 분기를 간결하게 작성합니다.val result = when (input) {
0 -> "Zero"
1 -> "One"
else -> "Unknown"
}fun computeValue(x: Int) = x * 2제한된 계층 구조를 가지는 sealed class를 활용하여 안전하게 다형성을 구현할 수 있습니다.
sealed class PersonState {
// data object는 Kotlin 1.9 이상에서 지원. (하위 버전에서는 object만 사용)
data object Running : PersonState()
data object Walking : PersonState()
data object Idle : PersonState()
}
fun getStateMessage(state: PersonState): String = when (state) {
is PersonState.Running -> "달린다."
is PersonState.Walking -> "걷는다."
is PersonState.Idle -> "쉰다."
}
if (obj is String) {
// obj는 자동으로 String 타입으로 스마트 캐스팅됨.
println(obj.length)
}class MyClass {
companion object {
const val CONSTANT = "상수값"
fun create(): MyClass = MyClass()
}
}reified 키워드 활용함수형 프로그래밍과 성능 최적화를 위해 inline 함수를 사용할 수 있습니다.
또한 Generic의 실제 타입 확인을 위해 reified 타입 파라미터를 사용할 수 있습니다.
inline fun <reified T> isInstance(value: Any): Boolean {
return value is T
}
fun main() {
println(isInstance<String>("Kotlin")) // true
println(isInstance<Int>("Kotlin")) // false
}
fun main() = runBlocking {
launch {
delay(1000L)
println("World!")
}
println("Hello,")
}