개발/Kotlin

[Kotlin In Action] 3. ν•¨μˆ˜ μ •μ˜μ™€ 호좜

도리 🐟 2021. 5. 10. 23:54

#1. ν•¨μˆ˜ 호좜

fun <T> joinToString(
        collection: Collection<T>,
        separator: String,
        prefix: String,
        postfix: String
): String {
    val result = StringBuilder(prefix)
    for ((index, element) in collection.withIndex()) {
        if (index > 0) result.append(separator)
        result.append(element)
}
    result.append(postfix)
    return result.toString()
}

 

이름 뢙인 인자

  • μžλ°”
joinToString(collection, /* separator */ " ",  /* prefix */ " ",
            /* postfix */ ".");

 

  • μ½”ν‹€λ¦°
joinToString(collection, separator = " ", prefix = " ", postfix = ".")

 

ν•¨μˆ˜μ— μ „λ‹¬ν•˜λŠ” 인자 쀑 일뢀(λ˜λŠ” μ „λΆ€)의 이름을 λͺ…μ‹œν•  수 μžˆλ‹€.
호좜 μ‹œ 인자 쀑 μ–΄λŠ ν•˜λ‚˜λΌλ„ 이름을 λͺ…μ‹œν•˜κ³  λ‚˜λ©΄ ν˜Όλ™μ„ 막기 μœ„ν•΄ κ·Έ 뒀에 μ˜€λŠ” λͺ¨λ“  μΈμžλŠ” 이름을 κΌ­ λͺ…μ‹œν•΄μ•Ό ν•œλ‹€.

μžλ°”λ‘œ μž‘μ„±ν•œ μ½”λ“œλ₯Ό ν˜ΈμΆœν•  λ•ŒλŠ” 이름 뢙인 인자λ₯Ό μ‚¬μš©ν•  수 μ—†λ‹€.
(코틀린은 JDK 6와 ν˜Έν™˜λœλ‹€.)

 

λ””ν΄νŠΈ νŒŒλΌλ―Έν„° κ°’

μ½”ν‹€λ¦°μ—μ„œλŠ” ν•¨μˆ˜ μ„ μ–Έμ—μ„œ νŒŒλΌλ―Έν„°μ˜ λ””ν΄νŠΈ 값을 지정할 수 μžˆμœΌλ―€λ‘œ, μ˜€λ²„λ‘œλ“œλ₯Ό 쀄일 수 μžˆλ‹€.

fun <T> joinToString(
        collection: Collection<T>,
        separator: String = ", ",
        prefix: String = "",
        postfix: String = ""
): Strin

 

μ½”ν‹€λ¦° ν•¨μˆ˜λ₯Ό μžλ°”μ—μ„œ ν˜ΈμΆœν•˜λŠ” κ²½μš°μ—λŠ” κ·Έ μ½”ν‹€λ¦° ν•¨μˆ˜κ°€ λ””ν΄νŠΈ νŒŒλΌλ―Έν„° 값을 μ œκ³΅ν•˜λ”λΌλ„ λͺ¨λ“  인자λ₯Ό λͺ…μ‹œν•΄μ•Ό ν•œλ‹€. @JvmOverloadsλ₯Ό ν•¨μˆ˜μ— μΆ”κ°€ν•˜λ©΄ μ½”ν‹€λ¦° μ»΄νŒŒμΌλŸ¬κ°€ μžλ™μœΌλ‘œ 맨 λ§ˆμ§€λ§‰ νŒŒλΌλ―Έν„°λ‘œλΆ€ν„° νŒŒλΌλ―Έν„°λ₯Ό ν•˜λ‚˜μ”© μƒλž΅ν•œ μ˜€λ²„λ‘œλ”©ν•œ μžλ°” λ©”μ„œλ“œλ₯Ό μΆ”κ°€ν•΄μ€€λ‹€.

 

μ΅œμƒμœ„ ν•¨μˆ˜

ν•¨μˆ˜λ₯Ό 직접 μ†ŒμŠ€ 파일의 μ΅œμƒμœ„ μˆ˜μ€€, 클래슀 밖에 μœ„μΉ˜μ‹œν‚¬ 수 μžˆλ‹€.

JVM이 클래슀 μ•ˆμ— λ“€μ–΄μžˆλŠ” μ½”λ“œλ§Œμ„ μ‹€ν–‰ν•  수 있기 λ•Œλ¬Έμ—, μ»΄νŒŒμΌν•  λ•Œ μƒˆλ‘œμš΄ 클래슀λ₯Ό μ •μ˜ν•΄μ€€λ‹€.

package strings;

public class JoinKt { //join.kt -> μ½”ν‹€λ¦° μ†ŒμŠ€ 파일 이름과 μžλ°” 클래슀 이름이 λŒ€μ‘λœλ‹€.
    public static String joinToString(...) { ... }
}

 

@file:JvmName("StringFunctions"): 클래슀 이름을 μ§€μ •ν•˜λŠ” μ• λ…Έν…Œμ΄μ…˜

 

μ΅œμƒμœ„ ν”„λ‘œνΌν‹°

ν”„λ‘œνΌν‹°λ„ μ΅œμƒμœ„ μˆ˜μ€€μ— 놓을 수 μžˆλ‹€.
-> 정적 ν•„λ“œμ— μ €μž₯λœλ‹€.

var opCount = 0

fun performOperation() {
    opCount++
    // ... 
}

fun reportOperationCount() {
    println("Operation performed $opCount times")
}

 

μ΅œμƒμœ„ ν”„λ‘œνΌν‹°λ₯Ό ν™œμš©ν•΄ μ½”λ“œμ— μƒμˆ˜λ₯Ό μΆ”κ°€ν•  수 μžˆλ‹€.

val UNIX_LINE_SEPARATOR = "\n"

 

μ΅œμƒμœ„ ν”„λ‘œνΌν‹°λ„ λ‹€λ₯Έ ν”„λ‘œνΌν‹°μ²˜λŸΌ μ ‘κ·Όμž λ©”μ„œλ“œλ₯Ό 톡해 μžλ°” μ½”λ“œμ— λ…ΈμΆœλœλ‹€.
const λ³€κ²½μžλ₯Ό μΆ”κ°€ν•˜λ©΄ ν”„λ‘œνΌν‹°λ₯Ό public static final ν•„λ“œλ‘œ μ»΄νŒŒμΌν•˜κ²Œ λ§Œλ“€ 수 μžˆλ‹€.
(primitive νƒ€μž…κ³Ό String νƒ€μž…λ§Œ const둜 지정할 수 μžˆλ‹€.)

#2. ν™•μž₯ ν•¨μˆ˜μ™€ ν™•μž₯ ν”„λ‘œνΌν‹°

ν™•μž₯ ν•¨μˆ˜

ν™•μž₯ ν•¨μˆ˜λŠ” μ–΄λ–€ 클래슀의 멀버 λ©”μ„œλ“œμΈ κ²ƒμ²˜λŸΌ ν˜ΈμΆœν•  수 μžˆμ§€λ§Œ, κ·Έ 클래슀의 밖에 μ„ μ–Έλœ ν•¨μˆ˜λ‹€.

  • μˆ˜μ‹  객체 νƒ€μž…(receiver type): 클래슀 이름
  • μˆ˜μ‹  객체(receiver object): ν™•μž₯ ν•¨μˆ˜κ°€ ν˜ΈμΆœλ˜λŠ” λŒ€μƒμ΄ λ˜λŠ” κ°’(객체)

ν™•μž₯ ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜κΈ° μœ„ν•΄μ„œλŠ” importν•΄μ•Ό ν•œλ‹€.

import strings.lastChar
val c = "Kotlin".lastChar()

import strings.lastChar as last //as ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜λ©΄ λ‹€λ₯Έ μ΄λ¦„μœΌλ‘œ λΆ€λ₯Ό 수 μžˆλ‹€.
val c = "Kotlin".last()

 

μžλ°”μ—μ„œ ν™•μž₯ ν•¨μˆ˜ 호좜 λ‚΄λΆ€μ μœΌλ‘œ ν™•μž₯ ν•¨μˆ˜λŠ” μˆ˜μ‹  객체λ₯Ό 첫 번째 인자둜 λ°›λŠ” 정적 λ©”μ†Œλ“œμ΄λ‹€.

char c = StringUtilKt.lastChar("Java");

 

ν™•μž₯ ν•¨μˆ˜λŠ” μ˜€λ²„λΌμ΄λ“œν•  수 μ—†λ‹€.

μˆ˜μ‹  객체둜 μ§€μ •ν•œ λ³€μˆ˜μ˜ 정적 νƒ€μž…μ— μ˜ν•΄ μ–΄λ–€ ν™•μž₯ ν•¨μˆ˜κ°€ ν˜ΈμΆœλ μ§€ κ²°μ •λœλ‹€.

- 클래슀의 멀버 ν•¨μˆ˜ 쀑 ν™•μž₯ ν•¨μˆ˜μ™€ 이름 및 μ‹œκ·Έλ‹ˆμ²˜κ°€ 같은 ν•¨μˆ˜κ°€ μžˆλ‹€λ©΄, 멀버 ν•¨μˆ˜κ°€ ν˜ΈμΆœλœλ‹€.
- 멀버 ν•¨μˆ˜μ˜ μš°μ„ μˆœμœ„κ°€ 더 λ†’λ‹€.

 

ν™•μž₯ ν”„λ‘œνΌν‹°

val String.lastChar: Char
    get() = get(length - 1)

 

λ’·λ°›μΉ¨ν•˜λŠ” ν•„λ“œ(Backing field)κ°€ μ—†μ–΄μ„œ κΈ°λ³Έ Getter κ΅¬ν˜„μ„ μ œκ³΅ν•  수 μ—†μœΌλ―€λ‘œ, μ΅œμ†Œν•œ GetterλŠ” κΌ­ μ •μ˜ν•΄μ•Ό ν•œλ‹€.
μ΄ˆκΈ°ν™” μ½”λ“œμ—μ„œ κ³„μ‚°ν•œ 값을 담을 μž₯μ†Œκ°€ μ—†μœΌλ―€λ‘œ, μ΄ˆκΈ°ν™” μ½”λ“œλ„ μ“Έ 수 μ—†λ‹€.

var StringBuilder.lastChar: Char
    get() = get(length - 1)
    set(value: Char) {
        this.setCharAt(length - 1, value) //μ‹€μ œλ‘œ ν™•μž₯ ν”„λ‘œνΌν‹°λŠ” 아무 μƒνƒœλ„ κ°€μ§ˆ 수 μ—†λ‹€.
    }

#3. κ°€λ³€ 인자 ν•¨μˆ˜

vararg ν‚€μ›Œλ“œ μ‚¬μš©

fun listOf<T>(vararg values: T): List<T> { ... }

 

μ½”ν‹€λ¦°μ—μ„œλŠ” 배열을 λͺ…μ‹œμ μœΌλ‘œ ν’€μ–΄μ„œ λ°°μ—΄μ˜ 각 μ›μ†Œκ°€ 인자둜 μ „λ‹¬λ˜κ²Œ ν•΄μ•Ό ν•œλ‹€.

fun main(args: Array<String>) {
    val list = listOf("args: ", *args) //μŠ€ν”„λ ˆλ“œ μ—°μ‚°μž(*)λ₯Ό 뢙이면 λ°°μ—΄μ˜ λ‚΄μš©μ„ νŽΌμ³μ€€λ‹€.
    println(list)
}

 

#4. κ°’μ˜ 쌍

μ€‘μœ„ 호좜

μΈμžκ°€ ν•˜λ‚˜λΏμΈ λ©”μ„œλ“œλ‚˜ ν™•μž₯ ν•¨μˆ˜μ— μ€‘μœ„ ν˜ΈμΆœμ„ μ‚¬μš©ν•  수 μžˆλ‹€.
μˆ˜μ‹  객체와 μœ μΌν•œ λ©”μ„œλ“œ 인자 사이에 λ©”μ„œλ“œ 이름을 λ„£μ–΄ ν˜ΈμΆœν•œλ‹€.
infixλ₯Ό ν•¨μˆ˜ μ„ μ–Έ μ•žμ— λΆ™μ—¬μ„œ, μ€‘μœ„ ν˜ΈμΆœμ„ ν—ˆμš©ν•  수 μžˆλ‹€.

infix fun Any.to(other: Any) = Pair(this, other)

1.to("one") //일반적인 λ°©μ‹μ˜ 호좜

1 to "one" //μ€‘μœ„ 호좜

 

ꡬ쑰 λΆ„ν•΄ μ„ μ–Έ

val (number, name) = 1 to "one" //두 λ³€μˆ˜λ₯Ό μ¦‰μ‹œ μ΄ˆκΈ°ν™”ν•  수 μžˆλ‹€.

 

λ£¨ν”„μ—μ„œλ„ ꡬ쑰 λΆ„ν•΄ 선언을 ν™œμš©ν•  수 μžˆλ‹€.

for ((index, element) in collection.withIndex()) {
    println("$index: $element")
}

 

#5. λ¬Έμžμ—΄

3쀑 λ”°μ˜΄ν‘œ (""")

3쀑 λ”°μ˜΄ν‘œ μ•ˆμ—μ„œλŠ” μ—­μŠ¬λž˜μ‹œλ₯Ό ν¬ν•¨ν•œ μ–΄λ–€ λ¬Έμžλ„ μ΄μŠ€μΌ€μ΄ν”„ν•  ν•„μš”κ°€ μ—†λ‹€.
μ€„λ°”κΏˆμ„ ν‘œν˜„ν•˜λŠ” 아무 λ¬Έμžμ—΄μ΄λ‚˜ κ·ΈλŒ€λ‘œ λ“€μ–΄κ°„λ‹€.

#6. 둜컬 ν•¨μˆ˜

ν•¨μˆ˜μ—μ„œ μΆ”μΆœν•œ ν•¨μˆ˜λ₯Ό 원 ν•¨μˆ˜ 내뢀에 μ€‘μ²©μ‹œν‚¬ 수 μžˆλ‹€.
둜컬 ν•¨μˆ˜λŠ” μžμ‹ μ΄ μ†ν•œ λ°”κΉ₯ ν•¨μˆ˜μ˜ λͺ¨λ“  νŒŒλΌλ―Έν„°μ™€ λ³€μˆ˜λ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€.

class User(val id: Int, val name: String, val address: String)

fun User.validateBeforeSave() {
    fun validate(value: String, fieldName: String) {
        if (value.isEmpty()) {
            throw IllegalArgumentException(
               "Can't save user $id: empty $fieldName")
        }
    }
    
    validate(name, "Name")
    validate(address, "Address")
}

fun saveUser(user: User) {
    user.validateBeforeSave()
    // Save user to the database
}

 

ν•œ κ°μ²΄λ§Œμ„ λ‹€λ£¨λ©΄μ„œ 객체의 λΉ„κ³΅κ°œ 데이터λ₯Ό λ‹€λ£° ν•„μš”λŠ” μ—†λŠ” ν•¨μˆ˜λŠ” ν™•μž₯ ν•¨μˆ˜λ‘œ λ§Œλ“€λ©΄

'객체.멀버'처럼 μˆ˜μ‹  객체λ₯Ό μ§€μ •ν•˜μ§€ μ•Šκ³ λ„ 곡개된 멀버 ν”„λ‘œνΌν‹°λ‚˜ λ©”μ„œλ“œμ— μ ‘κ·Όν•  수 μžˆλ‹€.