매일 한줄 코딩

#4. 코틀린 흐름 제어 ( if, for .. 등 ) 본문

develop/kotlin

#4. 코틀린 흐름 제어 ( if, for .. 등 )

ShipJH 2022. 6. 6. 23:20
4. 흐름 제어 - Control Flow

4. 흐름 제어 - Control Flow

목차

1. if-else 문

자바와 거의 비슷하다.

1-1. 일반 if문 , if else 문

var max = a
if ( a < b ) max = b // a가 b보다 크면 b를 반환해라.
var max: Int
if ( a > b ) {
	max = a  // a가 더 크면 max에 a를 넣고.
} else {
	max = b // 아니고, b가 더 크다면 max에 b를 넣는다.
}

1-2. 값을 반환하는 if else 문

  • if문이 식으로 사용되는 경우 값을 반환한다.
  • if식의 경우 반드시 else 를 동반해야 된다.
val max = if ( a > b ) a else b
// if 문이 식으로 사용되었다. 식의 값이 max의 값에 할당하게 된다. 
// val max = if (조건) true else false
// 반환값이 없으면 컴파일 에러.

  • if식의 브랜치들이 블록을 가질 수 있다. (브랜치란, 식의 if else 문의 식의 블록(구현부)라고 생각하면 된다.)
  • 블록의 마지막 구문이 반환 값이 된다.
val max = if ( a > b ) {
	print("a print")
	a
} else {
	print("b print")
	b
}
//위와 같은 경우에도 if의 조건이 true면 a를 반환하고, false 면 b를 반환한다.

1-3. 기타 특징

삼항 연산자가 없다. → if else 문이 이미 삼항연산자의 역할을 하기 때문이다.

//java 
int max = ( a > b ) ? a : b;

//kotlin
val max = if ( a > b ) a else b


2. when 문

2-1. 기본 when문.

  • when문은 C계열 언어의 switch문을 대체한다.
  • when문은 각각의 브랜치의 조건문이 만족할 때 까지 위에서 부터 순차적으로 인자를 비교한다.
when (x) {
	1 -> print("x == 1")
	2 -> print("x == 2")
	else -> {
		print("x is no 1,2")
	}
}

switch문의 brack가 필요없이, 나열하게 되면, 처음부터 비교하다가 맞는것이 나올때까지 실행된다.

마지막의 else는 swich 문의 default라고 생각하면 된다.

2-2. else가 필수인 when문

  • when문이 식으로 사용된 경우에, 브랜치의 값이 전체 식의 결과 값이 된다.
  • else의 경우 다른 브랜치들이 조건이 만족되지 않을 때에 수행된다.
  • when이 식으로 사용된 경우에는 else문이 필수이다.
var score = when(x) {
	100 -> "A"
	90 -> "B"
	80 -> "C"
	else -> "F"
}

2-3. else가 생략되어도 되는 when문

  • 단, else를 생략할 수 있는 경우도 있는데 이때에는 아래와같이 true / false (boolean 타입) 처럼 2가지중 하나를 입증할 수 있을 경우에는 생략할 수 있다. (컴파일러가 판단)
var score = when(x) {
	true -> "100"
	false -> "0"
} // true / false 와 같이 두가지 중 하나가 선택되는 경우 else 를 생략할 수 있다.

2-4. 여러 조건이 들어가는 when문

  • 여러 조건들이 들어가야된다면, 브런치안에 콤마(,) 를 사용하여 표현하면 된다.
when(x) {
	0, 1 -> print("x is 0,1")
	else -> print("not find")
}

2-5. 조건문에 함수나 식을 사용하는 when문

  • 브랜치의 조건문에 함수나 식을 사용 할 수 있다.
when(x) {
	parseInt(x) -> print("parsed x.") //함수도 사용가능.
	1 + 3 -> print("4") //식도 사용 가능.
	else -> print("not found.")
}

2-6. range나 collection에 in이나 !in(not in)으로 범위등을 검사할 수 있는 when문

val numbers = listOf(3,6,9)
when(x) {
    in numbers -> print("x is valid") // 3,6,9 중 하나일때,
    in 1..10 -> print("x in 1~10") // 1~10 사이일때,
    !in 10..20 -> print("x not in 10~20") // 10~20 사이가 아닐때,
    else -> print("not found.") // 모두 아닐경우.
}

2-7. is나 !is를 이용하여 타입도 검사할 수 있는 when문

  • 스마트 캐스트가 적용

    → Any(Object)로 받았을때 String으로 검사하는 동시에 startWith라는 함수를 사용가능하게 해준다.

fun main(args: Array<String>){
    val value: String = "prefixabc"
    print(hasPrefix(value))
}

fun hasPrefix(x: Any) = when(x) {
    is String -> x.startsWith("prefix") // prefix로 시작하면, true 반환
    else -> false // false반환
}

2-8. when은 if else if 체인 구문을 대체 할 수 있다.

  • when문의 인자를 입력하지 않았을때에 if else if else 반복되는 것을 하지 않고 대체가능하다.
var x: Int? = 1
when {
    x == 1 -> print("x is 1")
    x == 2 -> print("x is 2")
    else -> print("x is no 1,2")
}


3. For Loop문 (반복문)

3-1. 기본 For Loop문

  • for문은 iterator를 제공하는 모든것을 반복할 수 있다.

    list, array 는 .iterator() 를 사용할 수 있다. .iterator()를 반환하지 않는것을 for문에 작성할시 컴파일에러.

for (item in collection)
	print(item)

  • for문의 Body가 블록이 올 수 있다. (자바처럼)
for (item in collection) {
	print(item.id)
	print(tiem.name)
}

3-2. For문을 지원하는 iterator의 조건

  • iterator()를 반환하는 것이 있는 경우.
  • iterator()를 반환 하면서, next()를 가지는 경우
  • iterator()를 반환 하면서, hasNext(): Boolean을 가지는 경우.

‼️ 위 3가지 함수가 operator 로 표기되어있어야 함!

  • 예시)
fun main(args: Array<String>){
    val myData = MyData()
    myData.iterator()
    for(item in myData) {
        print(item)
    }
}

class MyIterator {
    val data = listOf(1,2,3,4,5)
    var idx = 0

    operator fun hasNext() : Boolean { // operator 필수~
        return data.size > idx
    }

    operator fun next() : Int { // operator 필수~
        return data[idx++]
    }
}

class MyData {
    operator fun iterator() : MyIterator { // operator 필수~
        return MyIterator()
    }
}

위 처럼, MyData는 list나 array가 아닌데, for문을 사용할 수 있었던 점은.

Mydata에서 operator로 선언된 iterator()를 반환해야하고,

또, MyIterator안에 operator의 hasNext()와 next()를 반환해야 가능하다.

그렇게 중요하진 않음.... ㅋㅋ

3-3. For문을 돌때 인덱스를 사용하고 싶다면 ?

  • indices를 이용한다.
val array = arrayOf("A","B","C")
for (item in array.indices) {
	println("$item: ${array[item]}")
}
/*
출력결과 
0: A
1: B
2: C
*/

  • withIndex()를 이용한다.
val array = arrayOf("A","B","C")
for ((index, value) in array.withIndex()) {
	println("$index: ${value}")
}
/*
출력결과 
0: A
1: B
2: C
*/

개인적으로 withIndex()가 더 명확한 소스로 보인다.


4. While Loop문 (반복문)

  • 자바와 유사하다. while, do-while 모두.
var x : Int = 3
while ( x > 0 ) {
    print(x)
    x = x-1
}

  • do-while문에서 body의 지역변수를 do-while문의 조건문이 참조 할 수 있다.
do {
	val y = retrieveData()
} while (y!=null) // y를 참조가능.
Comments