231214 TIL #268 Kotlin #3 enum / when / 스마트캐스트 / 이터레이션 / 예외처리

김춘복·2023년 12월 13일
0

TIL : Today I Learned

목록 보기
268/543
post-custom-banner

Today I Learned

코틀린 인 액션 이어서 공부!


선택 표현과 처리

enum

enum class Color(
    val r: Int, val g: Int, val b: Int
) {
    RED(255,0,0), GREEN(0,255,0),
    BLUE(0,0,255), YELLOW(255,255,0),
    VIOLET(238, 130, 238);
    
    fun rgb() = (r*256+g)*256+b
}
  • 자바에서는 enum이라고 그냥 쓰면 되지만 코틀린은 enum class 로 선언해야 한다.
    자바처럼 단순히 열거만 하지않고 프로퍼티나 메서드를 정의할 수 있다.

  • ()괄호 안에서 상수의 프로퍼티를 정의한다.

  • 각 상수마다 프로퍼티 값을 지정한다.

  • 메서드를 정의해야하면 상수 목록의 마지막에 세미콜론;을 넣어 구분이 필수


when

Java의 switch와 비슷한 역할. switch문과는 다르게 when은 if처럼 값을 만들어내는 이다.

fun getColorNum(color: Color) = when(color) {
        Color.RED, Color.YELLOW -> "warm"
        Color.GREEN, Color.BLUE -> "cold"
        Color.VIOLET -> "neutral"
    }
  • 위는 함수의 반환 값으로 when 식을 직접 사용한다.

  • 자바와는 달리 break;을 안넣어도 된다.

  • 콤마를 이용해 한 분기에서 여러 값을 매칭시킬 수 있다.

  • 위의 예시에서 Color를 import하면 RED, YELLOW -> "warm" 처럼 간단히 쓸 수 있다.

  • 분기 조건(when 뒤의 괄호)에 상수나 숫자 리터럴만 사용할 수 있는 자바 switch와는 다르게 코틀린은 분기조건으로 임의의 객체를 허용한다. setOf(a,b) 같은 객체를 넣으면 동등성(equality)검사 후 매칭되는 분기를 찾는다.

  • when의 인자가 없는 경우도 가능하다. 각 분기의 조건이 boolean 결과를 계산하는 식이면 된다.

  • if/when 모두 분기에 {}블럭을 쓸 수 있다. 이 경우 마지막 문장이 블록의 전체 결과가 된다.


스마트캐스트

변수나 프로퍼티의 타입을 자동으로 검사하고 해당 타입으로 캐스팅해주는 기능

  • 코드를 간결하게 작성할 수 있도록 도와주며, 안전한 형변환을 보장한다.

  • 컴파일러가 주체가 되어 스마트 캐스트를 수행해준다.

  • is를 사용해 변수 타입을 검사한다. 자바의 instanceof와 비슷하다.

fun printStringLength(value: Any) {
    if (value is String) {
        println(value.length)
    } else {
        println("Not a String")
    }
}
  • 위의 코드에서 if식 조건 안의 is가 value의 타입을 검사한 후, 그 식안에서 value는 자동으로 String으로 캐스팅된다. value.length가 작동하니 value가 자동으로 String이 되는 것이다.

    IDE가 스마트캐스팅을 표시해준다.
fun describe(value: Any) = when (value) {
        is String -> "It's a String with length ${value.length}"
        is Int -> "It's an Int"
        else -> "Unknown type"
    }
  • 위의 코드처럼 when 식과 함께 쓸 수도 있다. when(변수)를 써서 안의 분기에 is를 사용할 수 있다.
  • 클래스의 프로퍼티에 대해 스마트 캐스트를 사용하면 그 프로퍼티는 반드시 val이어야 한다.

  • as : 원하는 타입으로 명시적으로 캐스팅을 할때는 as를 쓴다.
    val n = e as Num


이터레이션

이터레이션에 사용되는 표현

  • range(범위)
    시작값..끝값의 형태로 시작과 끝값을 포함한 값들의 닫힌구간이다.
    여기서 마지막값도 범위 안에 포함된다.
    ex) val oneToTen = 1..10

  • in
    in을 이용해 어떤 값이 해당 범위에 속하는지 boolean 값으로 검사할 수 잇다.
    !in을 사용하면 범위에 속하지 않는지 검사할 수 있다.

  • downTo : 역방향 수열
    ex) 100 downTo 1 : 100부터 1까지 역방향 수열

  • step : 증가값의 절대값 변경
    ex) 15 downTo 1 step 2 : 15 13 11 ... 1 처럼 -2씩 진행되는 수열

  • until : 첫값~끝값-1. 자바에서 흔히 쓰는 방식
    ex) 0 until 10 : 0~9까지

for 루프

for 아이템 in 원소들 의 형태로 작성한다.
기본적으로 범위(range)를 사용해서 정수 단위 for문을 구현할 수 있다.

fun fizzBuzz(i: Int) = when {
    i % 15 == 0 -> "FizzBuzz "
    i % 5 == 0 -> "Fizz "
    i % 3 == 0 -> "Buzz "
    else -> "$i "
}

fun main(){
    for (i in 1..15){
        print(fizzBuzz(i))
    }
    println()
    for (i in 15 downTo 1 step 2){
        print(fizzBuzz(i))
    }
}
/* 출력값
1 2 Buzz 4 Fizz Buzz 7 8 Buzz Fizz 11 Buzz 13 14 FizzBuzz 
FizzBuzz 13 11 Buzz 7 Fizz Buzz 1 
*/

while

자바의 while과 딱히 다른 것이 없다.

while(조건) {
	// ...
}

do {
	// ...
} while(조건)

list

리스트의 withIndex() 메서드를 사용하면 index 값과 요소값을 같이 for문에서 순회할 수 있다.

    val list = arrayListOf(30, 40, 50, 80)
    for ((index, element) in list.withIndex()){
        println("$index: $element")
    }

map

fun main(){
    val binaryReps = TreeMap<Char, String>()

    for(c in 'A'..'F') { // A~F까지 문자 범위
        val binary = Integer.toBinaryString(c.code) // 아스키코드를 2진표현으로 교체
        binaryReps[c] = binary // c가 키이고 2진표현이 value로 map에 삽입
    }

    for ((letter, binary) in binaryReps){ // map을 이터레이션. 키와 밸류를 두 변수에 대입
        println("$letter = $binary")
    }
}

get, put 같은 메서드 대신 map[key] = value 로 map에 값을 삽입할 수 있다.
아래의 for문에서 map을 이터레이션해 출력한다.
map의 key와 value를 letter, binary라는 변수로 할당해 저장한다.


예외 처리

코틀린의 예외처리는 기본적으로 자바와 비슷하다.

  • throw

    기본적으로 예외를 던지는 방법으로, 자바에서와 달리 new를 사용하지 않아도 된다.
    그리고 자바에서와 달리 throw는 이므로 결과값이 있으며 다른 식에 포함될 수 있다.

fun divide(a: Int, b: Int): Int {
    if (b == 0) {
        throw IllegalArgumentException("${b}가 0이라서 나눌 수 없다.")
    }
    return a / b
}
  • try, catch, finally

fun readNumber(reader: BufferedReader): Int? {
    return try {
        val line = reader.readLine()
        Integer.parseInt(line)
    } catch (e: NumberFormatException){
        null;
    } finally {
        reader.close()
    }
}

기본적으로 throws 절이 없다. 자바에선 throws IOExecption을 붙여 checked exception을 명시적으로 처리하지만, 기본적으로 코틀린에서는 예외가 검사된 예외(checked exception)와 비검사된 예외(unchecked exception)로 구분되지 않는다.

  • try 식

    try는 if나 when 처럼 이다. 따라서 try 값을 변수에 대입할 수 있다.
    단, if와 달리 try는 본문을 반드시 중괄호{}로 감싸야 한다. 해당 블록의 마지막 값이 결과다.

fun readNumber2(reader: BufferedReader) {
    val number = try {
        Integer.parseInt(reader.readLine())
    } catch (e: NumberFormatException){
        null
    }
    println(number)
}
profile
Backend Dev / Data Engineer
post-custom-banner

0개의 댓글