ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Unit / Nothing
    🔖 Kotlin 2024. 11. 25. 12:20

    🎯 목표

    코틀린에는 return 하지 않아도 되는 반환 유형이 Unit 과 Nothing 두 가지가 존재한다.

    이 두 가지의 차이점을 알아보고 언제 어떤 반환 유형을 사용해야 할지 공부해보려고 한다.

    1️⃣ Unit

    Kotlin 에서 반환 유형을 지정하지 않은 경우 기본적으로 반환 유형이 Unit이 된다.

    • Java의 void와 비슷하지만, Kotlin에서는 Unit도 실제로 객체로 존재

     

    특징

    • Unit은 타입이면서 싱글톤 인스턴스로 매번 객체를 생성하지 않는다.
    • 함수의 반환값이 없더라도 Unit을 명시적으로 반환할 수 있다.
    • 기본적으로 반환값이 없는 함수는 Unit을 암시적으로 반환
    fun printMessage(message: String): Unit {
        println(message)
    }
    
    // 아래는 동일
    fun printMessage(message: String) {
        println(message)
    }
    

     

    2️⃣ Nothing

    Nothing 은 값을 반환하지 않는 경우를 나타내는 타입입니다.

    • 함수가 정상적으로 실행을 종료하지 않거나, 절대로 실행 흐름이 도달하지 않는 위치를 표시합니다.

     

    특징

    • Nothing 타입을 반환하는 함수는 정상적으로 반환하지 않고, 예외를 던지거나 프로그램이 종료
    • "실행 흐름이 끝나지 않는" 코드 위치를 나타내는 데 사용.
    • Nothing은 모든 타입의 하위타입으로, 모든 타입과 호환된다.

     

    📖 ”실행 흐름이 끝나지 않는 코드” 위치

    • 코드가 값을 반환하지 않거나, 실행이 멈추거나, 예외가 발생하여 정상적으로 종료되지 않는 위치를 의미
    • 즉, 이후 코드가 실행되지 않는 구역을 가리키며, 이는 다음과 같은 상황에서 발생할 수 있다.
      • 예외를 던지는 코드 (throw)
      • 프로그램을 강제로 종료하는 코드 (exitProcess)
      • 무한 루프

     

    🔖 정리

    특징 Unit Nothing
    의미 "아무 값도 반환하지 않는다." "실행 흐름이 이 위치에서 멈춘다."
    실행 흐름 함수가 정상적으로 실행을 끝낸 후 흐름을 계속 진행함 실행 흐름이 중단되고 이후 코드에 도달하지 않음
    사용 목적 반환할 값이 없을 때 사용 (e.g., println()) 함수가 절대 반환되지 않음을 나타냄 (e.g., throw, exitProcess)
    컴파일러 처리 반환 타입으로 Unit을 추론 이후 코드가 도달 불가능함을 컴파일러가 알 수 있음

     

    📌 Nothing의 활용

    1️⃣ 예외를 던지는 함수

    코틀린에서 throw는 표현식으로, Elvis 표현식의 일부로 사용할 수 있다.

    val grade = beomsic.grade ?: throw RuntimeException("")
    

     

    Nothing은 실행 흐름이 도달할 수 없는 구역을 나타내기 위한 특수 타입으로, throw 표현식은 Nothing 타입을 갖는다.

    throw 표현식은 항상 실행 흐름을 중단하기 때문에 반환값이 없습니다.

    따라서 throw의 타입은 Nothing

     

    fun throwException(message: String): Nothing {
        throw IllegalArgumentException(message)
    }
    

     

    설명

    • 위 함수는 항상 예외를 던지므로 정상적으로 종료되지 않는다.
    • 반환 타입을 Nothing으로 선언함으로써 이 함수가 절대 값을 반환하지 않는다는 것을 명시적으로 나타낸다.

     

    2️⃣ 도달할 수 없는 코드

    Nothing은 실행 흐름이 도달할 수 없는 구역을 표시하는 데 사용.

    예를 들어, when 표현식에서 모든 경우를 처리했지만, 여전히 기본값으로 예외를 처리하고 싶을 때 활용

     

    fun getColorCode(color: String): String {
        return when (color) {
            "red" -> "#FF0000"
            "green" -> "#00FF00"
            "blue" -> "#0000FF"
            else -> throw IllegalArgumentException("Unknown color: $color") // Nothing 타입
        }
    }
    

     

    설명

    • else 분기는 항상 예외를 던지므로 반환 타입이 Nothing.
    • 이는 Kotlin 컴파일러가 "모든 경우가 처리되었다"고 판단하게 한다.
    • 컴파일러는 else에서 예외를 던지면, Nothing 타입 때문에 더 이상 실행이 진행되지 않음을 알 수 있다.

     

    3️⃣ 실행을 멈추는 역할

    Nothing은 특정 조건에서 실행을 멈추는 역할도 합니다.

    예를 들어, 함수에서 프로그램 실행을 종료해야 할 때 사용

     

    fun terminateProgram(): Nothing {
        println("Program is terminating...")
        exitProcess(0) // 종료, 아무 값도 반환하지 않음
    }
    

     

    설명

    • 이 함수는 종료 후 반환값이 없으므로 Nothing 타입을 반환

     

    4️⃣ 타입 호환성

    Nothing은 Any 타입의 하위 타입이므로 어떤 타입에도 대입 가능

    예를 들어, throw 표현식이 들어가는 경우 Nothing은 자동으로 다른 타입과 호환된다.

    val number: Int = throw IllegalArgumentException("This is an error")
    

     

    설명

    • throw 표현식의 타입은 Nothing이지만, 이는 Int 타입과 호환됩니다.
    • 컴파일러는 실행 흐름이 여기서 끝난다는 것을 알기 때문에 오류 없이 코드를 처리

     

    5️⃣ 타입 추론

    Kotlin에서 Nothing? 는 null 값만 가질 수 있는 특별한 nullable 타입이다.

    컴파일러는 타입을 추론할 정보가 부족하고, 초기화 값이 null인 경우에 그 변수의 타입을 Nothing? 으로 추론한다.

     

    val test = null // Nothing?로 추론
    test?.length // 컴파일 오류: Nothing 타입에는 length 속성이 없음
    

     

    Nothing? 변수에 다른 타입의 값을 할당

    val test1 = null // Nothing? 타입
    val test2: String? = test1 // Nothing?은 String?에 할당 가능
    
    • Nothing?은 모든 nullable 타입의 하위타입이므로, String? 같은 넓은 범위의 nullable 타입으로 할당할 수 있다.

     

    명시적으로 타입을 지정한 경우

    val test: String? = null // test는 명시적으로 String? 타입
    
    • 이 경우, 컴파일러는 타입 정보를 제공받았으므로 Nothing?로 추론하지 않고 String?로 선언

     

    👍 Nothing 을 사용하는 이유와 이점

    1. 실행 흐름 중단을 명시
      • 코드가 정상적으로 끝나지 않음을 나타낸다.
      • 예외 처리, 프로그램 종료, 도달할 수 없는 코드의 존재를 명확히 보여준다.
    2. 모든 타입과 호환
      • 어떤 타입과도 호환되므로, 조건문이나 함수 반환값의 일부로 활용
    3. 코드 가독성 향상
      • 코드에서 예외를 던지거나 실행 흐름이 중단되는 위치를 직관적으로 이해 가능

     

    📖 Reference

    Unit

    Kotlin: Unit과 Nothing

    '🔖 Kotlin' 카테고리의 다른 글

    😎 Infix Function  (0) 2024.12.30
    널 안정성  (0) 2024.12.29
    🦥 lateinit 과 lazy  (0) 2024.12.29
    Kotlin Coroutines  (0) 2024.12.28
    Gradle Kotlin DSL  (3) 2024.11.21

    댓글

Designed by Tistory.