안녕하세요. 코틀린 #3

  1. 안녕하세요. 코틀린 #1
  2. 안녕하세요. 코틀린 #2
  3. 안녕하세요. 코틀린 #3

코틀린에서는 더 안전하고 편하게 null을 처리하고 형을 다룰 수 있습니다. 제어흐름도 더 깔끔합니다. 이번 편에서는 형과 제어 흐름에 대해 알아봅시다. 아쉽게도 이번이 이 시리즈의 마지막입니다.

null 처리와 캐스팅

찰스 앤터니 리처드 호어는 null을 컴퓨터 프로그래밍에 도입한 것에 대해 10억 달러 실수라고 부르며 책임감을 자기고 있습니다.


I call it my billion-dollar mistake. It was the invention of the null reference in 1965. At that time, I was designing the first comprehensive type system for references in an object oriented language (ALGOL W). My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn’t resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.


C.A.R. 호어의 자기 비판 후 많은 사람들은 null을 좀 더 나은 방법으로 해결하려 하였습니다. 코틀린도 예외는 아닙니다. 이제 코틀린이 어떻게 이 문제를 다루는지 살펴봅시다. 코틀린이 로컬에 설치되어 있다면 아래와 같이 입력해봅시다.

이런 개발 뉴스를 더 만나보세요

코틀린과 null

$ kotlin
>>> var hello : String = "Hello Realm"
>>> hello = null

String 타입으로 정의된 변수에 null 값을 대입하면 에러가 발생합니다.

error: null can not be a value of a non-null type kotlin.String
hello = null

코틀린에서 특정 타입으로 정의를 하면 기본으로 null 값을 허용하지 않는 변수가 정의되게 됩니다.

만약 null을 명시적으로 허용하고 싶다면 아래와 같이 코드를 작성해야 합니다.

>>> var hello2: String? = "Hello Realm2"
>>> hello2 = null

이제 hellohello2에 대해 length를 호출해봅시다.

>>> hello.length
11

hello.length는 문제가 전혀 없습니다만 hello2.length는 에러가 발생합니다.

>>> hello2.length
error: only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type kotlin.String?
hello2.length

hello2가 null이 될 수 있기 때문에 length를 호출할 수 없다는 것이지요. 코틀린은 자바에 비해 null 처리에 대해 까다롭습니다.

이를 해결할 간단한 방법은 null 값을 확인하는 방법입니다.

val l = if (hello2 != null) (hello2 as String).length else -1

코틀린에서의 캐스팅은 변수 as 타입의 형태로 이루어집니다. 캐스팅이 실패할 때면 ClassCastException을 반환하는데 이를 조용히 넘기기 위해서 as?를 사용할 수 있습니다.

안전 호출과 엘비스 오퍼레이터

안전 호출(Safe call)와 엘비스 오퍼레이터(Elvis operator)를 이용하면 더 간결하게 할 수 있습니다.

hello2 ?.length ?: -1

안전 호출(?.)은 앞의 타입이 null이 아닌 경우만 호출을 해서 값을 리턴하고 그렇지 않은 경우엔 null을 호출합니다. 엘비스 오퍼레이터(?:)는 앞의 값이 참이면 참인 값을 그대로 반환하고 아닌 경우에는 지정한 값을 반환합니다.

만약 Null pointer exception을 굳이 보고 싶다면 !! 연산자를 사용할 수 있습니다.

강제 호출

hello2!!.length()

이 방법을 굳이 사용할 일은 많지 않으실 겁니다.

자동 형변환

아래의 예제를 입력해봅시다.

fun getStringLength(something: Any): Int? {
    if (something is String) {
        return something.length
    }
    return null
}

somethingAny로 받았기 때문에 어떤 타입이든 받게 됩니다. 그런데 여기에서 보면 String으로의 변환만 있고 something의 타입은 더 이상 신경쓰지 않고 length를 호출한 것을 볼 수 있습니다. 자동 형변환 은if 문 밖에서도 가능합니다.

fun getStringLength(something: Any): Int? {
    if (something !is String) {
        return null;
    }
    return something.length
}

제어 흐름

코틀린은 자바와 비슷하게 제어 흐름을 가지고 있습니다. 유사한 부분(for, while)은 다루지 않고 차이가 있는 부분에 대해서 설명하겠습니다.

if

if는 표현식으로 사용될 수 있습니다. 구문으로만 사용가능한 자바와의 차이점입니다.

val max = if (a > b) {
        print("Choose a")
        a
    }
    else {
        print("Choose b")
        b
    }

when

when은 기존의 C 언어 형태의 switch 구문에 비해서 훨씬 유연하고 다양하게 사용할 수 있습니다.

when (x) {
    1 -> print("x == 1")
    2 -> print("x == 2")
    else -> {
        print("x is neither 1 nor 2")
    }
}

1, 2가 아닐때 else 부분이 수행됩니다.

when (x) {
    parseInt(s) -> print("s encodes x")
    else -> print("s does not encode x")
}

parseInt가 수행이 가능할 때와 아닐 경우로 케이스를 나눌 수 있습니다.

when (x) {
    in 1..10 -> print("x is in the range")
    in validNumbers -> print("x is valid")
    !in 10..20 -> print("x is outside the range")
    else -> print("none of the above")
}

in!도 사용할 수 있습니다.

val hasPrefix = when(x) {
    is String -> x.startsWith("prefix")
    else -> false
}

타입에 따라 수행할 수 있습니다.

when {
    x.isOdd() -> print("x is odd")
    x.isEven() -> print("x is even")
    else -> print("x is funny")
}

if-else 구문을 완전히 대체할 수 있습니다.

앞으로

이제 코틀린을 훑어 보았습니다. 더 자세한 내용을 알고 싶다면 온라인 튜토리얼이나 코틀린 사이트의 레퍼런스를 참고하면서 프로그래밍에 코틀린을 포함시켜 보세요. 특히 안드로이드와 코틀린의 조합은 굉장히 안정적이고 편리하니 자바로 개발하던 안드로이드 개발자라면 코틀린을 개발에 사용해 보세요.

다음: 안드로이드 아키텍처 #5: 액티비티와 프래그먼트에서 벗어나 간결하게 Android 앱 만들기

General link arrow white

컨텐츠에 대하여

이 컨텐츠는 저자의 허가 하에 이곳에서 공유합니다.


Leonardo YongUk Kim

Leonardo YongUk Kim is a software developer with extensive experience in mobile and embedded projects, including: several WIPI modules (Korean mobile platform based on Nucleus RTOS), iOS projects, a scene graph engine for Android, an Android tablet, a client utility for black boxes, and some mini games using Cocos2d-x.

4 design patterns for a RESTless mobile integration »

close