우주먼지
Published 2023. 3. 29. 05:18
Kotlin Controll Flow Languages/Kotlin

💡 if-else 문

  • if 문이 '식'으로 사용되는 경우 값을 반환한다.
  • if '식'의 경우 반다시 else를 동반해야 하지 않으면 컴파일 에러가 난다.
// a가 큰경우 max에 a를 대입, 아니면 b 대입
// 상항연산자와 구조가 동일하다
val max = if (a > b) a else b
  • if '식'의 branches들이 블록을 가질 수 있다. { ... }
  • 블록의 마지막 구문이 반환값이 된다.
fun if_else_식() {
    var a = 5
    var b = 4
    val max = if (a > b) {
        print("Choose a")
        a // 블록의 마지막 구문인 a가 반환값이 된다
    } else {
        print("Choose b")
        b // 블록의 마지막 구문인 b가 반환값이 된다
    }
}

그리고 코틀린에는 삼항연산자가 없다.

왜냐하면 if가 삼항연산자의 역할을 잘 해내기 때문이다.


💡 when 문

  • C계열 언어의 switch문을 대체한다.
  • 각각의 Branches의 조건문이 만족할 때까지 위에서부터 순차적으로 인자를 비교한다.
  • 조건이 맞으면 맞는 조건의 코드를 출력하기 때문에 break문을 쓸 필요가 없다.
when (x) {
    1 -> print("x == 1")
    2 -> print("x == 2")
    else -> {
        print("x is neither i nor 2")
    }
}
  • when 문도 if식처럼 '식'으로 사용하면 else 문이 필수이다.
  • 식으로 사용된 경우 1, 조건을 만족하는 branch의 값이 전체 식의 결과값이 된다.
  • 식으로 사용된 경우2 , else가 없어도 된다는걸 컴파일러가 입증하면 else를 생략 가능하다.
var res = when (x) {
    100 -> "A"
    90 -> "B"
    80 -> "C"
    else -> "F"
}

// else 문이 없어도 되는 케이스
var res = when (x) {
    true -> "맞다"
    false -> "틀리다"
}

여러 조건들이 같은 방식으로 처리될 수 있는 경우, 조건문에 ','를 사용하여 표기하면 된다.

when (x) {
    0, 1 -> print("x == 0 or x == 1")
    else -> print("otherwise")
}

branch의 조건문에 함수나 식을 사용 가능하다.

when (x) {
    parseInt(x) -> print("s encodes x")
    1 + 3 -> print("4")
    else -> print("s does not encode x")
}

range를 줘서 collection에 in이나 !in으로 범위 등을 검증할 수 있다.

val validNums = listOf(3,6,9)
when (x) {
    in validNums -> print("x is valid")
    in 1..10 -> print("x is in the range")
    !in 10..20 -> print("x is outside the range")
    else -> print("none of the above")
}

is, !is를 이용한 타입 검증, 이때 스마트 캐스팅이 적용된다.

fun hasPrefix(x: Any) = when (x) {
    is String -> x.startsWith("prefix")
    else -> false
}

if-else 체인을 완전히 대체할 수 있고, 인자를 입력하지 않으면, 논리연산으로 처리된다.

when {
    x.isOdd() -> print("x is odd")
    x.isEven() -> print("x is even")
    else -> print("x is funny")
}

💡 Loop

 

for문을 지원하는 iterator의 조건

  • 멤버함수나 확장함수 중에 iterator()를 반환하는 것이 있는 경우
  • next()를 가지는 경우
  • hasNext()를 [Boolean] 가지는 경우
  • 위의 3개의 함수는 operator로 표기되어야 함.

 

핵심은 Iterator를 가지고 있지 않는 MyData 객체가 For Each 문에 들어올 수 있다는 것이다.

일반적인 코틀린의 for문은 iterator를 제공하는 모든 것을 반복할 수 있고, Body에 블럭이 올 수도 있다.

fun 반복() {

    var collection = listOf(1,2,3,4,5)
    collection.iterator()
    for (i in collection)
        print(i)

    val array = arrayOf(1,2,3,4,5)
    array.iterator()
    for (i in array)
        println("$i: $array[i]")
}

 

연산자 오버로딩을 이용한 iterator()가 없는 객체 For-Each 구현

여기서 봐야할 중요한 점은,
위에서 말한 조건들을 구현하면 iterator()를 가지고 있지 않는 객체도 For-Each를 돌 수 있다.

// 아래의 두 클래스로 인해
// Iterator를 가지고 있지 않는 MyData 객체가 For Each 문에 들어올 수 있다.
fun main(args: Array<String>) {
    val myData = MyData()
    myData.iterator()

    for (i in myData) {
        print(i)
    }
}

// next(), hasNext()를 가지고 있는 클래스
class MyIterator {
    val data = listOf(1,2,3,4,5)
    var idx = 0

    operator fun hasNext() : Boolean {
        return data.size > idx
    }

    operator fun next() : Int {
        return data[idx++]
    }
}

// MyIterator 객체를 반환하는 클래스
class MyData {
    operator fun iterator() : MyIterator {
        return MyIterator()
    }
}

 

indices & withIndex()

배열이나 리스트를 index를 이용하여 반복하고 싶을때 사용한다.

val array = arrayOf("가", "나", "다")
for (i in array.indices) {
    println("$i: ${array[i]}")
}

 

index를 이용하고 싶을 때, withIndex()를 사용한다.

인덱스와 값이 같이 반환된다.

val array = arrayOf("가", "나", "다")
for ((index, value) in array.withIndex()) {
    println("$index: ${value}")
}

 

While Loop

  • whild, do-whild은 자바의 거의 같다.
  • do-while의 조건문이 body의 지역변수를 참조할 수 있다.
while (x > 0) {
    x--
}

// do 안의 지역변수인 y를 while에서 참조가 가능하다
do {
    val y = retrieveData()
} while (y != null) // y is Visible Here !
profile

우주먼지

@o귤o

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

검색 태그