제어문(Control Flow)
- 저는 전문 번역가도 아니고, 의역을 넘어 오역, 심지어 그냥 제가 읽고 싶은대로 읽은 내용이 있을 수 있습니다.
- 개인 공부를 한 것을 포스트로 남기고 있으며 틀린 부분이 있으면 지적해주시면 수정하도록 하겠습니다.
- 원문 : https://play.kotlinlang.org/byExample/02_control_flow/01_When
When
널리 사용하는 switch
문(statement) 대신에 코틀린은 조금 더 유연하고 깔끔한 when
문(construction)을 제공합니다. when
문은 statement
와 expression
으로 사용될 수 있습니다.
When Statement
fun main() {
cases("Hello")
cases(1)
cases(0L)
cases(MyClass())
cases("hello")
}
fun cases(obj: Any) {
when (obj) { // 이것이 when statement 입니다.
1 -> println("One") // obj가 1과 같은지 검사합니다.
"Hello" -> println("Greeting") // obj가 Hello와 같은지 검사합니다.
is Long -> println("Long") // obj가 Long타입인지 검사합니다.
!is String -> println("Not a string") // obj가 String타입이 아닌지 검사합니다.
else -> println("Unknown") // 디폴트(default) 상황에서는 해당 구문이 실행됩니다.(생략 가능)
}
}
class MyClass
모든 분기는 조건 중에 하나를 만족할 때까지 순차적으로 실행됩니다. 그렇기 때문에 가장 먼저 조건에 부합하는 분기만 실행될 것입니다.
When Expression
fun main() {
println(whenAssign("Hello"))
println(whenAssign(3.4))
println(whenAssign(1))
println(whenAssign(MyClass()))
}
fun whenAssign(obj: Any): Any {
val result = when (obj) { // 이것이 when expression 입니다.
1 -> "one" // obj가 1과 같으면 값에 "one"이 설정됩니다.
"Hello" -> 1 // obj가 Hello와 같으면 값에 1이 설정됩니다.
is Long -> false // obj가 Long타입의 인스턴스라면 값에 false가 설정됩니다.
else -> 42 // 앞에 있는 조건을 하나도 만족하지 못한 경우 값에 42가 설정됩니다.
}
return result
}
class MyClass
when statement
와는 다르게 when expression
에서는 디폴트 분기(else)가 대부분 있어야 합니다. (컴파일러가 앞에 있는 케이스가 가능한 모든 케이스를 커버한다고 판단할 수 있는 경우를 제외하면 when expression
에서는 else
가 반드시 있어야합니다.)
반복문(Loops)
코틀린은 일반적으로 사용되는 모든 반복문을 지원합니다. (for
, while
, do-while
)
for
코틀린에서 for
는 대부분의 프로그래밍 언어와 동일하게 동작합니다.
val cakes = listOf("carrot", "cheese", "chocolate")
for (cake in cakes) { // 리스트(cakes)에 있는 케이크를 반복합니다.
println("Yummy, it's a $cake cake!")
}
while, do-while
코틀린에서 while
, do-while
은 대부분의 프로그래밍 언어와 유사하게 동작합니다.
fun eatACake() = println("Eat a Cake")
fun bakeACake() = println("Bake a Cake")
fun main(args: Array<String>) {
var cakesEaten = 0
var cakesBaked = 0
while (cakesEaten < 5) { // condition이 true인 동안 블럭을 실행합니다.
eatACake()
cakesEaten ++
}
do { // 블럭을 한 번 실행하고, condition을 체크합니다.
bakeACake()
cakesBaked++
} while (cakesBaked < cakesEaten)
}
Iterator
내가 만든 클래스에 iterator 연산자를 구현하여 나만의 iterator를 정의할 수 있습니다.
class Animal(val name: String)
class Zoo(val animals: List<Animal>) {
operator fun iterator(): Iterator<Animal> { // 1
return animals.iterator() // 2
}
}
fun main() {
val zoo = Zoo(listOf(Animal("zebra"), Animal("lion")))
for (animal in zoo) { // 3
println("Watch out, it's a ${animal.name}")
}
}
- 클래스에 iterator를 정의합니다. 메소드 이름은 반드시
iterator
여야하고 앞에operator
라는 키워드를 붙여야만 합니다. - 다음 메소드 요구사항을 만족하는 iterator를 리턴합니다.
- next() : Animal
- hasNext() : Boolean
- zoo(iterator를 구현했음) 안에 있는 animal을 반복합니다.
iterator는 타입이나 확장함수로 선언될 수 있습니다.
Ranges
코틀린에는 범위(ranges)를 정의하기 위한 여러 방법이 있습니다.
for(i in 0..3) { // 0 부터 3(포함)까지 1씩 증가하면서 반복
print(i)
}
print(" ")
for(i in 2..8 step 2) { // 2 부터 8(포함)까지 2씩 증가하면서 반복 (custom increment step)
print(i)
}
print(" ")
for (i in 3 downTo 0) { // 3 부터 0까지 역순으로 반복
print(i)
}
print(" ")
// result : 0123 2468 3210
Char
ranges도 지원합니다.
for (c in 'a'..'d') { // 알파벳순으로 char 범위를 반복합니다.('d'포함)
print(c)
}
print(" ")
for (c in 'z' downTo 's' step 2) { // char ranges도 'step'과 'downTo' 키워드를 지원합니다.
print(c)
}
print(" ")
// result : abcd zxvt
if
문에서 range는 유용합니다.
val x = 2
if (x in 1..5) { // 값이 범위(1 부터 5)에 있는지 검사합니다.
print("x is in range from 1 to 5")
}
println()
if (x !in 6..10) { // !in은 in의 반대입니다. (포함되지 않는지 검사합니다.)
print("x is not in range from 6 to 10")
}
동등성 검사(Equality Checks)
코틀린은 구조 비교를 위해 ==
연산자를 사용하고 참조 비교를 위해 ===
연산자를 사용합니다.
명확하게, a == b
를 a == null ? b == null : a.equals(b)
로 컴파일합니다.
(a가 null이면 b가 null인지에 따라 true, false리턴, a가 null이 아니면 a.equals(b)의 결과 리턴)
val authors = setOf("Shakespeare", "Hemingway", "Twain")
val writers = setOf("Twain", "Shakespeare", "Hemingway")
println(authors == writers) // 1
println(authors === writers) // 2
true
리턴, authors.equals(writers)를 호출하기 때문이고set
은 컬렉션에 저장된 요소의 순서를 무시하기 때문에 구조적으로 같다고 판단한다.false
리턴, authors와 writers가 다른 참조값을 갖기 때문이다.
Conditional Expression
코틀린에는 삼항연산자 condition ? then : else
가 없습니다. 대신 if
가 expression
으로 사용됩니다. (statement
가 아니다.)
fun max(a: Int, b: Int) = if (a > b) a else b //if는 expression으로 동작하고 값을 리턴합니다.
println(max(99, -42))
사설
기본적인 분기 처리고 눈으로 봤을 때 이해가 어려운 부분은 없지만 막상 사용하려고 코드를 쳐보면 어색하거나 문법이 기억이 안 나는 경험을 했습니다...
사용해버릇하면 좋을 것 같습니다.