Android

[Android] 코틀린(Kotlin) 함수(Function)

구루싸 2020. 4. 18. 13:02
반응형
SMALL

코틀린 학습 3일차가 되었네요

오늘은 코틀린의 함수를 학습하겠습니다

const val MAX_EXPERIENCE: Int = 500

private fun formatHealthStatus(healthPoints: Int, isBlessed: Boolean): String {
    val healthStatus = when (healthPoints) {
        100 -> "In best condition"
        in 90..99 -> "There are some abrasions"
        in 75..89 -> if (isBlessed) {
            "There are minor wounds, but they are healing quickly"
        } else {
            "There are minor wounds"
        }
        in 15..74 -> "A lot of hurt"
        else -> "Worst"
    }
    return healthStatus
}

private fun printPlayerStatus(auraColor: String, isBlessed: Boolean, name: String, healthStatus: String) {
    println("(Aura: $auraColor) " + "(Blessed: ${if (isBlessed) "YES" else "NO"})")
    println("$name $healthStatus")
}

private fun auraColor(isBlessed: Boolean, healthPoints: Int, isImmortal: Boolean): String {
    val auraVisible = isBlessed && healthPoints > 50 || isImmortal
    val auraColor = if (auraVisible) "GREEN" else "NONE"
    return auraColor
}

private fun castFireball(numFireBall: Int = 2) {
    println("A chunk of fireball appears. (x$numFireBall)")
}
/*
function overloading
 */
private fun performCombat() {
    println("No enemy")
}
private fun performCombat(enemyName: String) {
    println("Started a battle with $enemyName")
}
private fun performCombat(enemyName: String, isBlessed: Boolean) {
    if (isBlessed) {
        println("Started a battle with $enemyName. Blessed")
    } else {
        println("Started a battle with $enemyName")
    }
}

private fun shouldReturnAString(): String {
    TODO("Nothing Test")
    println("Code that can never be executed")
}
/*
backtick function
 */
private fun `**~prolly not a good idea!~**`() {
    println("This is backick function")
}
private fun runSimulation() {
    val greetingFunction = configureGreetingFunction()
    println(greetingFunction("GuruSa"))
}
/*
inline cannot use recursive function
 */
private inline fun runSimulation(playerName: String,
                                 costPrinter: (Int) -> Unit,
                                 greetingFunction: (String, Int) -> String) {
    val numBuildings = (1..3).shuffled().last()
    costPrinter(numBuildings)
    println(greetingFunction(playerName, numBuildings))
}
private fun printConstructionCost(numBuildings: Int) {
    val cost = 500
    println("Construction cost: ${cost * numBuildings}")
}
private fun configureGreetingFunction(): (String) -> String {
    val structureType = "Hospital"
    var numBuildings = 5
    return { playerName: String ->
        val currentYear = "2020"
        numBuildings += 1
        println("Add $numBuildings $structureType")
        "Welcome to SimVillage, $playerName! (copyright $currentYear)"
    }
}

fun main(args: Array<String>) {
    val name = "GuruSa"
    var healthPoints = 89
    var isBlessed = true
    val isImmortal = false

    val auraColor = auraColor(isBlessed, healthPoints, isImmortal)
    val healthStatus = formatHealthStatus(healthPoints, isBlessed)

    printPlayerStatus(auraColor, isBlessed, name, healthStatus)
    castFireball()
    `**~prolly not a good idea!~**`()

    /* lambda
    -> anonymous function
    -> closure = close over
    */
    val greetingFunction: (String, Int) -> String = { playerName, numBuildings ->
        val currentYear = "2020"
        println("Add $numBuildings Buildings")
        "Welcome to SimVillage, $playerName! (copyright $currentYear)"
    }
    runSimulation("GuruSa", ::printConstructionCost, greetingFunction)
    runSimulation("GuruSa", ::printConstructionCost) { playerName, numBuildings ->
        val currentYear = "2020"
        println("Add $numBuildings Buildings")
        "Welcome to SimVillage, $playerName! (copyright $currentYear)"
    }
    runSimulation()
    shouldReturnAString()
}

위의 코드에서 아래의 함수를 통해 간단히 살펴보겠습니다

private fun formatHealthStatus(healthPoints: Int, isBlessed: Boolean): String {
    val healthStatus = when (healthPoints) {
        100 -> "In best condition"
        in 90..99 -> "There are some abrasions"
        in 75..89 -> if (isBlessed) {
            "There are minor wounds, but they are healing quickly"
        } else {
            "There are minor wounds"
        }
        in 15..74 -> "A lot of hurt"
        else -> "Worst"
    }
    return healthStatus
}

"private"는 가시성 제한자로 붙이지 않는다면 코틀린은 "public"으로 인식합니다

"fun"은 함수임을 나타내며 formatHealthStatus는 이름입니다

위의 코드에서 `**~prolly not a good idea!~**`() 함수가 있는데

backtick(`) 기호를 이용하여 이름을 자유롭게 설정할 수도 있습니다

"healthPoints: Int, isBlessed: Boolean"은 파라미터로

함수 호출시에 인자로 Int, Boolean형을 넣을 수 있습니다

끝에 : "String"은 이 함수가 끝나고 반환(return)해주는 타입을 말합니다

코틀린에서는 이 반환 타입과 return문이 없는 함수를 Unit 함수라고합니다

Unit 함수는 아래의 함수를 말합니다

private fun performCombat() {
    println("No enemy")
}
private fun shouldReturnAString(): String {
    TODO("Nothing Test") //Nothing
    println("Code that can never be executed")
}

 

보통 다른 언어에서는 Void로 쓰고 있는데

코틀린은 Void의 단점을 보완하고자 Unit를 이용합니다

또 Nothing 타입이 있는데 TODO() 함수가 대표적인 예입니다

Nothing 타입을 반환하면 제어권이 넘어오지 않습니다

위의 코드에서 shouldReturnAString() 함수에서

TODO()함수를 호출하고 있는데요

TODO() 함수가 Nothing 타입을 반환하므로

제어권이 넘어오지 않고 예외가 발생하게 됩니다

함수의 파라미터만 다르게 설정하여 여러개 작성할 수 있는

함수 오버로딩(function overloading)을 제공하며

"inline"를 붙이면 함수를 호출하는 쪽에 해당 함수 부분을 붙여넣기하여

함수가 호출될 때 객체로 전달되지 않습니다

마지막으로 람다(lambda)에 대해 알아보고 마치겠습니다

/* lambda
-> anonymous function
-> closure = close over
*/
val greetingFunction: (String, Int) -> String = { playerName, numBuildings ->
  val currentYear = "2020"
  println("Add $numBuildings Buildings")
  "Welcome to SimVillage, $playerName! (copyright $currentYear)"
}

위에서 {}로 묶여있는 부분이 바로 람다(lambda)로

익명 함수(anonymous function)이며 클로저(closure)입니다

위의 코드에서 greetingFunction은

(String, Int) -> String 함수형 타입을 가지는 변수로

이 익명 함수를 대입한 것입니다

클로저이기 때문에 다른 함수에 포함된 함수에서 

자신을 포함하는 함수의 매개변수와 변수를 사용할 수 있습니다

private fun runSimulation() {
    val greetingFunction = configureGreetingFunction()
    println(greetingFunction("GuruSa"))
    println(greetingFunction("GuruSa"))
}
private fun configureGreetingFunction(): (String) -> String {
    val structureType = "Hospital"
    var numBuildings = 5
    return { playerName: String ->
        val currentYear = "2020"
        numBuildings += 1
        println("Add $numBuildings $structureType")
        "Welcome to SimVillage, $playerName! (copyright $currentYear)"
    }
}

runSimulation() 부분에서 호출부를 하나 더 추가하고

결과를 확인하면 클로저의 느낌을 알 수 있을 것 같습니다

아무튼 이것으로 오늘의 학습을 마치겠습니다

그럼 이만-_-

반응형
LIST