코틀린 인 액션 이어서 공부!
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 로 선언해야 한다.
자바처럼 단순히 열거만 하지않고 프로퍼티나 메서드를 정의할 수 있다.
()괄호 안에서 상수의 프로퍼티를 정의한다.
각 상수마다 프로퍼티 값을 지정한다.
메서드를 정의해야하면 상수 목록의 마지막에 세미콜론;
을 넣어 구분이 필수
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")
}
}
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"
}
클래스의 프로퍼티에 대해 스마트 캐스트를 사용하면 그 프로퍼티는 반드시 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 아이템 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(조건) {
// ...
}
do {
// ...
} while(조건)
리스트의 withIndex() 메서드를 사용하면 index 값과 요소값을 같이 for문에서 순회할 수 있다.
val list = arrayListOf(30, 40, 50, 80)
for ((index, element) in list.withIndex()){
println("$index: $element")
}
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라는 변수로 할당해 저장한다.
코틀린의 예외처리는 기본적으로 자바와 비슷하다.
기본적으로 예외를 던지는 방법으로, 자바에서와 달리 new를 사용하지 않아도 된다.
그리고 자바에서와 달리 throw는식
이므로 결과값이 있으며 다른 식에 포함될 수 있다.
fun divide(a: Int, b: Int): Int {
if (b == 0) {
throw IllegalArgumentException("${b}가 0이라서 나눌 수 없다.")
}
return a / b
}
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는 if나 when 처럼
식
이다. 따라서 try 값을 변수에 대입할 수 있다.
단, if와 달리 try는 본문을 반드시 중괄호{}로 감싸야 한다. 해당 블록의 마지막 값이 결과다.
fun readNumber2(reader: BufferedReader) {
val number = try {
Integer.parseInt(reader.readLine())
} catch (e: NumberFormatException){
null
}
println(number)
}