
μμ΄ν 11. κ°λ μ±μ λͺ©νλ‘ μ€κ³νλΌ
λ‘λ²νΈ λ§ν΄μ ν΄λ¦° μ½λ ... "κ°λ°μκ° μ½λ μμ±νλ λ°λ 1λΆ κ±Έλ¦¬μ§λ§, μ½λ λ°λ 10λΆμ΄ κ±Έλ¦°λ€."
κ°λ μ±μ΄λ, μ½λλ₯Ό μ½κ³ μΌλ§λ λΉ λ₯΄κ² μ΄ν΄ν μ μλμ§λ₯Ό μλ―Ένλ€.
// A
if (persion != null && person.isAdult) {
view.showPerson(person)
} else {
view.showError()
}
// B
person?.takeIf { it.isAdult }
?.let(view::showPerson)
?: view.showError()
Aκ° μ½κ³ μ΄ν΄νκΈ°κ° μ¬μ΄λ°, κΈ°λ³Έμ μΌλ‘ 'μΈμ§ λΆν'λ₯Ό μ€μ΄λ λ°©ν₯μΌλ‘ μ½λλ₯Ό μμ±νλΌκ³ νλ€.
100% 곡κ°μ΄ λμ§λ μλλ€. ν¨μν νλ‘κ·Έλλ°μ μ μ΅νκ³ , μ μ¬μ©νλ€λ©΄ μΆ©λΆν μ½κ³ μ΄ν΄νκΈ° μ¬μ°λ©°, μ± μμ λ§νλ 'μΈμ§ λΆν' μΈ‘λ©΄μμλ μ€νλ € λ μ€μΌ μ μμ§ μμκΉ..? μκ°νλ€.
κ°λ μ±μ 'λκ° νλ‘κ·Έλ¨μ μλ λ°©μμ μ΄ν΄νλ κ³Όμ 'μ λ μ§§κ² λ§λλ κ²
λνμ μΌλ‘ ν¨μ μΆμΆ, μΆμν λ±μ μμ μ΄ μμ κ² κ°λ€.
students
.filter { it.result >= 50 }
.joinToString(separator = "\n") { "${it.name} ${it.surname}, ${it.result}" }
.let(::print)
var obj = FileInputStream("/file.gz")
.let(::BufferedInputStream)
.let(::ZipInputStream)
.let(::ObjectInputStream)
.readObject() as SomeObject
letμ μ¬μ©νκΈ° μ’μ 2κ°μ§ μμλ?
- μ°μ°μ μκ·λ¨ΌνΈ μ²λ¦¬ νμ νΈμΆν λ
- λ°μ½λ μ΄ν°λ₯Ό μ¬μ©ν΄ κ°μ²΄λ₯Ό λ©ν λ
μμ΄ν 12. μ°μ°μ μ€λ²λ¬λλ₯Ό ν λλ μλ―Έμ λ§κ² μ¬μ©νλΌ
μλ―Έμ λ§μ§ μκ² μ¬μ©ν μμ (ν©ν λ¦¬μΌ κ΅¬ν)
fun Int.factorial(): Int = (1..this).product()
fun Iterable<Int>.product(): Int = fold(1) { acc, i -> acc * i}
operator fun Int.not() = factorial()
fun main() {
println(!6) // 720
println(6.not()) // 720
}
μ ꡬν λ°©μμ λ¬Έμ μ ?
- ν¨μ μ΄λ¦κ³Ό μ€μ λμμ΄ μΌμΉνμ§ μλλ€.
- notμ λ Όλ¦¬ μ°μ°μ μν κ²μΈλ°, ν©ν λ¦¬μΌ κ³μ°μ μ¬μ©λμ΄ νΌλμ μ€ μ μλ€.
μ½νλ¦° μ°μ°μμ νΉμ§
- λͺ¨λ μ°μ°μλ ν¨μμ λ³μΉμ΄λ€.
- κ° μ°μ°μμ μλ―Έλ μΌκ΄λκ² μ μ§λμ΄μΌ νλ€.
μ°μ°μμ μλ―Έκ° λͺ ννμ§ μμ κ²½μ°,
tripledHello = 3 * { print("Hello") }
μ μ½λλ ν¨μλ₯Ό 3λ² λ°λ³΅νλ "μλ‘μ΄ ν¨μ μμ±"μ μλ―Ένλμ§, ν¨μλ₯Ό μ¦μ 3λ² νΈμΆνλ μ§ λͺ ννμ§ μλ€.
μμ κ²½μ° infix ν¨μλ₯Ό μ¬μ©νμ¬ μλλ₯Ό λͺ νν ν μ μλ€.
infix fun Int.timesRepeated(operation: () -> Unit) = {
repeat(this) { operation() }
}
fun main() {
val tripledHello = 3 timesRepeated { print("Hello") }
}
Infix ν¨μλ₯Ό μ¬μ©νλ λνμ μΈ μμ (Map)
val days = mapOf("Monday" to "μμμΌ", "Tuesday" to "νμμΌ")
μμ΄ν 13. Unit? μ 리ν΄νμ§ λ§λΌ
μ±μ© μΈν°λ·° κ³Όμ μμ νμμ μΉκ΅¬λ βν¨μμμ Unitμ 리ν΄νλ€λ©΄, κ·Έ μ΄μ λ 무μμΌκΉμ?β λΌλ μ§λ¬Έμ λ°μλ€.
Booleanμ΄ true/false λ₯Ό κ°λ κ²μ²λΌ, Unit?μ Unit, nullμ΄λΌλ κ°μ κ°μ§ μ μλ€.
fun keyIsCorrect(key: String): Boolean = key.length > 5
fun verifyKey(key: String): Unit? = if (key.length > 5) null else Unit
if (!keyIsCorrect(key)) return
verifyKey(key) ?: return
μ§κΈκΉμ§ μ¬λ¬ μ½λλ₯Ό 보면μ Unit?μ μ½κ² μ½μ μ μλ κ²½μ°λ κ±°μ λ³΄μ§ λͺ»νκ³ , μ€ν΄λ₯Ό λΆλ¬ μΌμΌν€κΈ° μ½λ€.
κΈ°λ³Έμ μΌλ‘ Unit?μ 리ν΄νκ±°λ, μ΄λ₯Ό κΈ°λ°μΌλ‘ μ°μ°νμ§ μλ κ²μ΄ μ’λ€.
Unit vs Void vs Nothing
μμ΄ν 14. λ³μ νμ μ΄ λͺ ννμ§ μμ κ²½μ° νμ€νκ² μ§μ νλΌ
μ½νλ¦°μ κ°λ°μκ° νμ μ μ§μ νμ§ μμλ νμ μ μ§μ ν΄μ λ£μ΄ μ£Όλ κ΅μ₯ν μμ€ λμ νμ μΆλ‘ μμ€ν μ κ°μΆκ³ μλ€.
μ΄λ κ°λ° μκ°μ μ€μ¬μ€ λΏλ§ μλλΌ, μ νμ΄ λͺ νν λ μ½λκ° μ§§μμ Έμ κ°λ μ± λν ν₯μλλ€.
νμ§λ§ μ νμ΄ λͺ ννμ§ μμ λ λ¨μ©νλ κ²μ μ’μ§ μλ€.
// Bad
val data = getSomeData()
// Good
val data: UserData = getSomeData()
κ°λ μ±μ μν΄ μ½λλ₯Ό μ€κ³ν λλ μ¬λμκ² μ€μν μ 보λ₯Ό μ¨κ²¨μλ μ λλ€.
μμ¦ λλΆλΆ IDEμμ νμ μ 보μ¬μ£Όλ (Inlay Hints) κΈ°λ₯μ μ 곡νκΈ° λλ¬Έμ λλΆλΆμ μν©μμλ κ΅³μ΄ νμ μ μ μν νμκ° μμκΉ? νλ μκ°μ΄κΈ΄ νλ€.
(GitHubμ κ°μ΄ μ½λ리뷰 ν λ μΉμ¬μ΄νΈ μμμλ νμ μ΄ νμΈμ΄ λΆκ°λ₯ν΄μ μ‘°κΈ λΆνΈν μ μ μμμ§λ§, μ΄λ¬ν κ²½μ° μ μΈ..)
νμ μ΄ nullableμ΄κ±°λ, μλμλ λ€λ₯Έ κ²½μ°, μ¬λ¬ μ°μ°μ΄ ν¬ν¨λμ΄ νμ μΆλ‘ μ΄ νλ κ²½μ° λ± λͺ νν νμ μ μκ° νμν κ²½μ°μλ§ μ μΈν΄λ μΆ©λΆνμ§ μμκΉ μΆλ€.
μμ΄ν 15. 리μλ²λ₯Ό λͺ μμ μΌλ‘ μ°Έμ‘°νλΌ
μλ΅ν μ μλ κ²½μ°μλ thisλ₯Ό λͺ μμ μΌλ‘ μ¬μ©νμ¬ μ½λλ₯Ό μμ±νλ κ²½μ°κ° μλ€.
λν μ¬λ¬ κ°μ 리μλ²κ° μλ μν©μμλ 리μλ²λ₯Ό λͺ μμ μΌλ‘ μ μ΄ μ£Όλ κ²μ΄ μ’λ€.
// block: (T) -> R μΌλ°μ μΈ ν¨μ μ μ
val block: (Int) -> Int = ...
block(3)
// block: T.() -> R κ°μ²΄ Tλ₯Ό receiver λ‘ νμ©ν Lambda with receiver
val block: Int.() -> Int = ...
100.block(3)
리μλ²(Receiver): κ°μ²΄ μΈλΆμ λλ€ μ½λ λΈλ‘μ λ§μΉ ν΄λΉ κ°μ²΄ λ΄λΆμμ μ¬μ©νλ κ² μ²λΌ μμ±ν μ μκ² ν΄μ£Όλ μ₯μΉ
block : T.() -> R
μ λλ€ λΈλ‘μ κ°μ²΄ Tλ₯Ό receiverλ‘ μ΄μ©νμ¬ κ°μ²΄ Rμ λ°ννλ€.
μμμ κ°μ²΄ Tλ₯Ό 리μλ²λΌ λΆλ₯΄κ³ , 리μλ²λ₯Ό μ¬μ©νλ λλ€λ₯Ό Lambda with receiver λΌκ³ λΆλ₯Έλ€.
μ°Έκ³ : https://jaeyeong951.medium.com/kotlin-lambda-with-receiver-5c2cccd8265a
μμ΄ν 16. νλ‘νΌν°λ λμμ΄ μλλΌ μνλ₯Ό λνλ΄μΌ νλ€
μ½νλ¦°μ νλ‘νΌν°μλ λ§μ κΈ°λ₯λ€μ΄ μ‘΄μ¬νλ€.
var name: String? = null
get() = field?.uppercase()
set(value) {
if (!value.isNullOrBlank()) {
field = value
}
}
μ½νλ¦°μμλ νλμ λν μ κ·Όμ λ©μλ(getter, setter)λ₯Ό μλμΌλ‘ μμ±νλ€. λλ¬Έμ νλ λμ νλ‘νΌν°λΌλ μ©μ΄λ₯Ό μ¬μ©νλλ°, μν κ²½μ° μ κ·Όμ λ©μλλ₯Ό λͺ μμ μΌλ‘ μ μΈν μλ μλ€.
Backing Field
backing fieldλ νλ‘νΌν°μ κ°μ μ μ₯νκΈ° μν νλμ΄λ€.
backing fieldλ νλ‘νΌν°μ κ°μ μ μ₯νκΈ° μν νλλ€. μ½νλ¦°μμλ νλλ₯Ό λ°λ‘ μ μΈν μ μκ³ νλ‘νΌν°λ‘ μ μΈνλ©΄ κΈ°λ³Έμ μΌλ‘ backing fieldκ° μμ±λλ€.
class KotlinProperty {
var counter = 0
set(value) {
if (value >= 0) field = value
}
}
// Java
public class KotlinProperty {
private int counter = 0;
public int getCounter() {
return counter;
}
public void setCounter(int value) {
if (value >= 0) {
this.counter = value;
}
}
}
μ΄λ€ κ²μ νλ‘νΌν°λ‘ ν΄μΌ ν μ§ νλ¨ν μ μλ κ°λ¨ν μ§λ¬Έμ, "μ΄ νλ‘νΌν°λ₯Ό ν¨μλ‘ μ μν κ²½μ° μ λμ¬λ‘ get/setμ λΆμΌ κ²μΈκ°? λ§μ½ μλλΌλ©΄, μ΄λ₯Ό νλ‘νΌν°λ‘ λ§λλ κ²μ μ’μ§ μλ€."
μ‘°κΈ λ ꡬ체μ μΌλ‘ νλ‘νΌν° λμ ν¨μλ₯Ό μ¬μ©νλ κ²μ΄ μ’μ κ²½μ°,
- μ°μ° λΉμ©μ΄ λκ±°λ 볡μ‘λκ° ν° κ²½μ°
- λΉμ¦λμ€ λ‘μ§μ ν¬ν¨νλ κ²½μ°
- λ³νμ κ²½μ° (toString(), toInt())
- getterμμ νλ‘νΌν°μ μν λ³κ²½μ΄ μΌμ΄λμΌ νλ κ²½μ°
μμ΄ν 17. μ΄λ¦ μλ μκ·λ¨ΌνΈλ₯Ό μ¬μ©νλΌ
val text = (1..10).joinToString("|")
μ μ½λμμ joinToString ν¨μμ μκ·λ¨ΌνΈμ | κ° μλ―Ένλ λ°λ, ν΄λΉ ν¨μλ₯Ό λͺ¨λ₯Έλ€λ©΄ μ΄ν΄νκΈ° νλ€ μ μλ€.
val text = (1..10).joinToString(separator = "|")
λ°λΌμ μ μ²λΌ μκ·λ¨ΌνΈλ₯Ό λͺ μμ μΌλ‘ μ¬μ©νμ¬ μμ±ν μ μλ€.
κ·Έλ λ€λ©΄, μμ κ°μ μ΄λ¦ μλ μκ·λ¨ΌνΈλ₯Ό μΈμ μ¬μ©ν΄μΌ ν κΉ?
- default μκ·λ¨ΌνΈμ κ²½μ°,
- κ°μ νμ μ νλΌλ―Έν°κ° λ§μ κ²½μ°,
- ν¨μ νμ μ νλΌλ―Έν° (ν¨μ νμ νλΌλ―Έν°λ λ§μ§λ§ μμΉμ λ°°μΉνλ κ²μ΄ μ’λ€.)
λνμ μΌλ‘ μμ κ°μ κ²½μ° μ΄λ¦ μλ μκ·λ¨ΌνΈλ₯Ό μ¬μ©νλ κ²μ΄ μ’κ² λ€.
κ·Έλ λ€λ©΄, μ΄λ¦ μλ μκ·λ¨ΌνΈλ₯Ό μ¬μ©νλ©΄ λ¬΄μ¨ μ₯μ μ κ°μ§κΉ?
- μ΄λ¦μ κΈ°λ°μΌλ‘ κ°μ΄ 무μμ λνλ΄λμ§ μ μ μλ€.
- νλΌλ―Έν° μ λ ₯ μμμ μκ΄ μμΌλ―λ‘ μμ νλ€.
μ΄λ¦ μλ μκ·λ¨ΌνΈλ κ°λ°μκ° μ½λλ₯Ό μ½μ λλ νΈλ¦¬νκ² νμ©λλ©°, μ½λμ μμ μ±λ ν₯μμν¬ μ μλ€.
@kotlin.internal.InlineOnly
public inline fun repeat(times: Int, action: (Int) -> Unit) {
contract { callsInPlace(action) }
for (index in 0 until times) {
action(index)
}
}
// μ¬μ© μμ
fun main() {
repeat(5) { index ->
println("Hello! This is message #${index + 1}")
}
}
λ§μ½ ν¨μ νμ μ νλΌλ―Έν°κ° λ§μ§λ§ μμΉκ° μλ κ²½μ°, μλ μ²λΌ κ°λ μ±μ΄ μ’μ§ μλ€.
@kotlin.internal.InlineOnly
public inline fun repeat(action: (Int) -> Unit, times: Int) {
contract { callsInPlace(action) }
for (index in 0 until times) {
action(index)
}
}
repeat(action = { println(it) }, times = 5)
μμ΄ν 18. μ½λ© 컨벀μ μ μ§μΌλΌ
- IDEμ formatter νμ©
- μ μ λΆμ λꡬ (ktlint, sonarqube λ±) νμ©
https://kotlinlang.org/docs/coding-conventions.html
Coding conventions | Kotlin
kotlinlang.org
'Kotlin' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
μ΄νν°λΈ μ½νλ¦° - 4μ₯ μΆμν μ€κ³ (1) | 2025.07.12 |
---|---|
μ΄νν°λΈ μ½νλ¦° - 3μ₯ μ¬μ¬μ©μ± (0) | 2025.06.25 |
μ΄νν°λΈ μ½νλ¦° - 1μ₯ μμ μ± (0) | 2025.06.03 |
Kotlin Collection (1) - (forEach, onEach, filter, filterNot, map, mapNotNull, flatMap, fold, reduce, sum, sumOf) (0) | 2025.02.09 |
Kotlin for iterator (1) | 2025.01.17 |
λκΈ