Kotlin - 02. 코틀린 기초

Kotlin 기초

Kotlin 의 기초로서, 아래 항목을 확인해보겠다.

  • 함수와 변수
  • 클래스와 프로퍼티
  • 선택 표현과 처리
  • 이터레이션
  • 예외 처리

함수와 변수 Function & Variable

함수

fun main(args: Array<String>) {
    println("Hello, Kotlin!")
}

Kotlin 함수 특징

  • 함수 선언은 fun 키워드를 사용한다.
  • 파라미터 이름 뒤에 타입을 지정한다.
  • 자바와 달리 꼭 클래스 안에 함수를 넣어야 할 필요가 없다.
  • 코틀린 표준 라이브러리의 함수는 여러 가지 표준 자바 라이브러리 함수를 간결하게 사용할 수 있도록 감싼 Wrapper 를 제공한다.
    • eg. println()
  • 세미콜론을 붙이지 않는다.
Kotlin 함수 기본 형식

Kotlin 함수 형식

식이 본문인 함수
fun max(a: Int, b: Int): Int = if (a > b) a else b

// 반환 타입 생략 가능 (타입 추론 `type inference`)
fun max(a: Int, b: Int) = if (a > b) a else b

변수

val question = "삶, 우주, 그리고 모든 것에 대한 궁극적인 질문"
val answer = 42

Kotlin 변수 특징

  • 변수의 타입은 표기 생략 가능하다.
  • 변경 가능한 변수(variable) 와 변경 불가능한 변수(value) 로 나눠진다.
    • var : variable 이란 뜻으로, 변경 가능(mutable)한 변수
    • val : value 이란 뜻으로, 변경 불가능한(immutable) 변수
  • val 참조 자체는 불변일지라도, 그 참조가 가리키는 객체의 내부 값은 변경될 수 있다.
val languages = arrayListOf("Java")
languages.add("Kotlin")
  • var 변수는 값을 변경할 수는 있지만, 타입은 고정되어 변경 불가능하다.

Kotlin 의 간편한 문자열 템플릿 string template

fun main(args: Array<String>) {
    val name = if (args.size > 0) args[0] else "Kotlin"
    println("Hello, $name!")
    // Java : System.out.println("Hello, " + name + "!");

    if (args.size < 0) {
        println("Hello, ${args[0]}!")
    }
}
  • 특정 변수를 선언하여 문자열 리터럴 안에 그 변수를 사용 가능하다.
  • 해당 문법은 Java 코드로 변환하면, JavaString + 연산 처럼 StringBuilder 를 사용한 append 문자열 빌더 뒤에 추가되는 바이트 코드를 생성한다.

클래스와 프로퍼티 Class & Property

클래스

Java 와 Kotlin 의 클래스 선언 차이

Java
public class Person {
    private final String name;

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}
Kotlin
class Person(
    val name: String
)
  • Kotlin 에서 클래스의 기본 가시성은 public 이므로 생략 가능하다.
  • Property 라는 개념을 통해서 Java 에서의 private 지시자와 getter 와 같은 접근자 메소드를 생략이 가능하다.

프로퍼티

프로퍼티 property 란 개념을 활용하는 프레임워크 (or 기술 스펙) 이 많지만, Kotlin 에서는 다음과 같이 언어 기본 기능으로 제공한다.

Kotlin 의 프로퍼티 property 정의

  • Java 클래스의 필드 field 와 접근자 메소드 getter 를 대신하는 개념이다.
  • 물론, 커스텀 접근자 메소드를 별도 구현 가능하다.
class Rectangle(
    val height: Int,
    val width: Int
) {
    val isSquare: Boolean
    	get() {
            return height == width
        }
}

Kotlin 소스코드 구조: 디렉토리와 패키지

  • Kotlin 에서는 Java 와 달리 하나의 클래스안에 파일명과 동일한 클래스 하나만 존재할 필요는 없다.
  • 하나의 .kt 클래스 안에는 여러 가지의 클래스 집합이 존재 가능하며, 각 클래스 파일 별로 import 또한 가능하다.

선택 표현과 처리

enum 클래스

기본 enum 클래스 형식

enum class Color {
    RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET
}
  • Kotlinenum 클래스도 역시, Java 문법과 동일하게 열거형 뿐만 아니라 프로퍼티나 메소드를 별도 정의하여 다양한 프로그래밍이 가능하다.

When

fun getMnemonic(color: Color) =
	when (color) {
        Color.RED -> "Richard"
        Color.ORANGE -> "Of"
        ...
        Color.BLUE, Color.INDIGO -> "cold"
    }
  • 별도의 break 를 넣지 않아도 된다.
  • 한 분기 안에 여러 값을 매치 패턴으로 사용한다면, , 콤마로 분리하여 정의 가능하다.

임의의 객체를 함께 사용하는 경우

fun mix(c1: Color, c2: Color) =
	when (setOf(c1, c2)) {
        setOf(RED, YELLOW) -> ORANGE
        ...
        else -> throw Exception("Dirty Color")
    }

인자 없는 when 정의

fun mix(c1: Color, c2: Color) =
	when {
        (c1 == RED && c2 == YELLOW || c1 == YELLOW && c2 == RED) -> ORANGE
        ...
        else -> throw Exception("Dirty Color")
    }

스마트 캐스트 smart cast & when 조합

// (1 + 2) + 4 산술식 구현
fun eval(e: Expr): =
	when (e) {
		is Num -> e.value
        is Sum -> eval(e.left) + eval(e.right)
	}

interface Expr
class Num(val value: Int) : Expr
class Sum(val left: Expr, val right: Expr) : Expr

이터레이션 iteration

// 증가 iterator
for (i in 1..100) {
    println(i)
}
// 1, 2, 3 ...

// 감소 iterator
for (i in 100 downTo 1 step 2) {
    println(i)
}
// 100, 98, 96 ...

// Map iterator
val colors = mapOf("R" to "RED", "G" to "GREEN", "B" to "BLUE")
for ((c, name) in colors) {
    println("$c name is $name")
}

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

fun recognize(c: Char) = when (c) {
    in '0'..'9' -> "It's digit!"
    in 'a'..'z', in 'A'..'Z' -> "It's a letter!"
    else -> "I don't konw.."
}

예외 처리

fun readNumber(reader: BufferedReader): Int? {
    try {
        val line = reader.readLine()
        return Integer.parseInt(line)
    } catch (e: NumberFormatException) {
        return null
    } finally {
        reader.close()
    }
}
  • Kotlin 에서는 throws 절이 없다.
  • checked exceptionunchecked exception 를 구별하지 않는다.
  • Java 에서는 무의미한 예외를 던지지만, 정작 처리되지 않는 코드들이 많기 때문에 Kotlin 에서는 이와 같은 throws 절을 없앴다.
  • try 는 식으로도 사용 가능하다.
  • 그래서, catch 에서도 값 반환이 가능하다.

체크 예외 vs 언체크 예외

체크 예외 checked exception
  • RuntimException 을 상속하지 않는 예외 클래스
  • 체크 예외가 발생 가능한 메소드를 사용할 경우, 복구가 가능한 예외들이므로 반드시 예외 처리 코드 필요 (catch 문을 통한 예외 처리 or throws 예외 처리)
  • IOException, SQLException
언체크 예외 unchecked exception
  • RuntimeException 을 상속한 예외 클래스
  • 명시적으로 예외 처리를 강제하지 않음
  • 언체크 예외는 프로그램에 오류가 있을 때 발생하도록 의도된 예외 처리
  • NullPointerException, IllegalArgumentException

출처