코틀린 & Java/코틀린인액션

[Kotlin] 기본 요소 함수와 변수에 대해 알아보자 (2)

코딩하는후운 2024. 3. 19. 13:56
반응형

함수와 변수

#While 루프

while (조건) {
	/*...*/      //조건이 참인 동안 본문을 반복 실행한다.
}

do {
	/*...*/
} while (조건)  //맨 처음에 무조건 본문을 한 번 실행한 다음, 조건이 참인 동안 본문을 반복 실행한다.

#범위와 수열

  • 자바의 for 루프(어떤 변수를 초기화하고 그 변수를 루프가 한 번 실행할 때마다 갱신하고 루프 조건이 거짓이 될 때 반복을 마치는 형태의 루프)에 해당하는 요소가 없다.
  • 이를 대신하기 위해 코틀린에서는 **범위(range)**를 이용한다.
fun fizzBuzz(i: Int) = when {
	i % 15 == 0 -> "FizzBuzz"
	i % 3 == 0 -> "Fizz"
	i % 5 == 0 -> "Buzz"
	else -> "$i"
}

>>> for (i in 1..100) { // 1..100 범위의 정수에 대해 이터레이션 한다.
	...print(fizzBuzz(i))
}
1 2 Fizz 4 Buzz Fizz 7 ...
  • 코틀린의 범위는 폐구간 또는 양끝을 포함하는 구간이다!

<aside> 💡 이터레이션(iteration) - 정수 범위로 수행할 수 있는 가장 단순한 작업 즉, 결과를 생성하기위한 프로세스의 반복 수열(progression) - 어떤 범위에 속한 값을 일정한 순서로 이터레이션 하는 경우

</aside>

for (i in 100 downTo 1 step 2) { // 100 downTo 1 은 역방향 수열, step 2 증가값의 절댓값
	...print(fizzBuzz(i))
}
Buzz 98 Fizz 94 92 FizzBuzz 88 ...
for (i in 0 until size) { // 0..size-1와 같은 반만 닫힌 범위

#map

val binaryReps = TreeMap<Char, String>()
for (c in 'A'..'F') { // A부터 F까지 문자의 범위를 사용해 이터레이션한다.
	val binary = Integer.toBinaryString(c.toInt()) //아스키 코드를 2진 표현으로 바꾼다.
	binaryReps[c] = binary // c를 키로 c의 2진 표현을 맵에 넣는다. 
                         // 자바 : binaryReps.put(c, binary)
}

for((letter, binary) in binaryReps) {
	println("$letter = $binary")
}

>>>
A = 1000001
B = 1000010
C = 1000011
D = 1000100
E = 1000101
F = 1000110

맵에 사용했던 구조 분해 구문을 맵이 아닌 컬렉션에도 활용할 수있다.

val list = arrayListOf("10", "11", "1001")
for ((index, element) in list.withIndex()) {
	println("$index: $element")
}

>>>
0: 10
1: 11
2: 1001 

#in으로 컬렉션이나 범위의 원소 검사

in 연산자를 사용해 어떤 값이 범위에 속하는지 검사할 수 있다.

반대로 !in을 사용하면 어떤 값이 범위에 속하지 않는지 검사할 수 있다.

fun isLetter(c: Char) = c in 'a'..'z' || c in 'A'..'Z'
fun isNotDigit(c: Char) = c !in '0'..'9'

>>> println(isLetter('q'))
true
>>> println(isNotDigit('x'))
true

비교가 가능한 클래스라면(java.lang.Comparable 인터페이스를 구현한 클래스라면) 그 클래스의 인스턴스 객체를 사용해 범위를 만들 수있다.

Interface Comparable 정렬 수행 시 기본적으로 적용되는 정렬 기준이 되는 메서드를 정의하는 인터페이스 package: java.lang.Comparable Java에서 제공되는 정렬이 가능한 클래스들은 모두 Comparable 인터페이스를 구현하고 있으며, 정렬 시에 이에 맞게 정렬이 수행된다.

// Integer class
public final class Integer extends Number implements Comparable<Integer> { ... }
// String class
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { ... }

Ex) Integer, Double 클래스: 오름차순 정렬 Ex) String 클래스: 사전순 정렬

>>> println("Kotlin" in "Java".."Scala") //"Java" <= "Kotlin && "Kotlin" <= "Scala"
true

String에 있는 Comparable 구현이 두 문자열을 알파벳 순서로 비교하기 때문에 여기 있는 in 검사에서도 문자열을 알파벳 순서로 비교한다.

컬렉션도 마찬가지로 in 연산을 사용할 수 있다.

>>> println("Kotlin" in setOf("Java", "Scala")) // 이 집합에는 Kotlin 없음
false

#예외 처리

코틀린의 예외 처리는 자바나 다른 언어의 예외 처리와 비슷하다.

자바와 달리 코틀린의 throw는 식이므로 다른 식에 포함될 수 있다.

val percentage = 
	if(number in 0..100)
		number
	else
		throw IllegalAgumentException(
			"A percentage value must be between 0 and 100: $number")

try 를 식으로 사용

fun readNumber(reader: BufferedReader) {
	val number = try {
		Interger.parseInt (reader.readLine()) // 이 식의 값이 "try"식의 값이 된다.
	} catch (e: NumberFormatException) {
		return
	}
	println(number)
}

>>> val reader = BufferedReader(StringReader("not a number"))
>>> readNumber(reader)  // 아무것도 출력되지 않음

catch에서 값 반환하기

fun readNumber(reader: BufferedReader) {
	val number = try {
		Interger.parseInt (reader.readLine()) // 이 식의 값이 "try"식의 값이 된다.
	} catch (e: NumberFormatException) {
		null
	}
	println(number)
}

>>> val reader = BufferedReader(StringReader("not a number"))
>>> readNumber(reader) 
null

반응형