Kotlin Reference - Basics / Basic Syntax

이준영·2020년 12월 9일
0

Kotlin Reference

목록 보기
1/1
post-thumbnail

이 글은 Kotlin Reference(v1.4.21)를 번역(?)해 보면서 학습한 내용을 정리한 글입니다.

영어가 익숙하지 않아 잘못된 번역이 있을 수 있습니다. 학습을 하면서 개인적인 생각(주석으로 표시)도 포함되어 있을 수 있으니, 이 부분을 감안하고 봐주시면 감사하겠습니다 🙇🏻‍♂️

Package definition and imports

패키지의 명세는 소스 파일의 맨 위에 위치해야 합니다.

package my.demo

import kotlin.text.*

// ...

소스 파일은 파일 시스템에서 임의로 배치될 수 있기 때문에 디렉토리와 패키지를 일치시킬 필요는 없습니다.

Program entry point

Kotlin 애플리케이션의 entry point는 main 함수입니다.

fun main() {
    println("Hello, world!")
}

Functions

이 함수는 두 개의 Int 매개변수와 Int 반환 타입을 가집니다:

fun sum(a: Int, b: Int): Int {
    return a + b
}

이 함수는 표현식으로 구성되어 있고 유추된 반환 타입을 가집니다:

fun sum(a: Int, b: Int) = a + b

반환 타입을 유추하는 것은 표현식으로 함수가 작성된 경우에만 가능합니다. 블록으로 함수를 정의한 경우에는 반환 타입을 명시해줘야 합니다 (Unit 타입 제외)

이 함수는 의미 없는 값을 반환합니다:

fun printSum(a: Int, b: Int): Unit {
    println("sum of $a and $b is ${a + b}")
}

(의미 없는 반환값인) Unit 반환 타입은 생략할 수 있습니다:

fun printSum(a: Int, b: Int) {
    println("sum of $a and $b is ${a + b}")
}

Variables

읽기-전용 지역 변수(Read-only local variable)는 val 이란 키워드로 선언할 수 있습니다. 이는 한 번만 값을 할당할 수 있습니다:

val a: Int = 1  // immediate assignment
val b = 2   // `Int` type is inferred
val c: Int  // Type required when no initializer is provided
c = 3       // deferred assignment

Java에서는 final 키워드로 이와 같은 역할을 하는 변수를 선언할 수 있었습니다. 그러나 변수의 선언과 동시에 할당을 해야만 했는데, Kotlin은 선언한 후에 할당을 하는 것도 가능합니다.

var 키워드로 선언한 변수(variables)는 값을 재할당 할 수 있습니다:

var x = 5 // `Int` type is inferred
x += 1

최상위(Top-level) 변수입니다:

val PI = 3.14
var x = 0

fun incrementX() { 
    x += 1 
}

Comments

대부분의 현대 언어들처럼, 단일 행(single-line, end-of-line) 주석과 블록(block) 주석을 제공합니다:

// This is an end-of-line comment

/* This is a block comment
   on multiple lines. */

블록 주석은 중첩이 가능합니다:

/* The comment starts here
/* contains a nested comment */     
and ends here. */

String templates

var a = 1
// simple name in template:
val s1 = "a is $a" 

a = 2
// arbitrary expression in template:
val s2 = "${s1.replace("is", "was")}, but now is $a"

Java 진영의 템플릿 엔진(thymeleaf, mustache 등)과 비슷한 것 같습니다.

Conditional expressions

fun maxOf(a: Int, b: Int): Int {
    if (a > b) {
        return a
    } else {
        return b
    }
}

Kotlin에서는 if 또한 표현식으로 사용될 수 있습니다:

fun maxOf(a: Int, b: Int) = if (a > b) a else b

Nullable values and null checks

null 값이 가능한 참조에는 null 일 수 있다고(nullable) 명시적으로 표시해야 합니다.

(아래는) str 이 integer가 아닐 경우 null 을 반환합니다:

fun parseInt(str: String): Int? {
    // ...
}

null 일 수 있는 함수를 사용합니다:

fun printProduct(arg1: String, arg2: String) {
    val x = parseInt(arg1)
    val y = parseInt(arg2)

    // Using `x * y` yields error because they may hold nulls.
    if (x != null && y != null) {
        // x and y are automatically cast to non-nullable after null check
        println(x * y)
    }
    else {
        println("'$arg1' or '$arg2' is not a number")
    }    
}

또는

// ...
if (x == null) {
    println("Wrong number format in arg1: '$arg1'")
    return
}
if (y == null) {
    println("Wrong number format in arg2: '$arg2'")
    return
}

// x and y are automatically cast to non-nullable after null check
println(x * y)

Type checks and automatic casts

is 연산자는 표현식이 어떤 타입(type)의 인스턴스(instance)인지 확인합니다. 만약, 불변 지역 변수(immutable local variable)나 속성(property)이 특정한 타입으로 확인되면, 명시적으로 형 변환(cast)을 하지 않아도 됩니다:

fun getStringLength(obj: Any): Int? {
    if (obj is String) {
        // `obj` is automatically cast to `String` in this branch
        return obj.length
    }

    // `obj` is still of type `Any` outside of the type-checked branch
    return null
}

또는

fun getStringLength(obj: Any): Int? {
    if (obj !is String) return null

    // `obj` is automatically cast to `String` in this branch
    return obj.length
}

또는 심지어

fun getStringLength(obj: Any): Int? {
    // `obj` is automatically cast to `String` on the right-hand side of `&&`
    if (obj is String && obj.length > 0) {
        return obj.length
    }

    return null
}

어떤 위치에서든 앞에서 나온 조건들로 타입을 특정할 수 있다면, 이후에 명시적인 형 변환을 하지 않아도 가능한 것 같습니다.

for loop

val items = listOf("apple", "banana", "kiwifruit")
for (item in items) {
    println(item)
}

Java의 Enhanced for loop 에 해당하는 것 같습니다.

또는

val items = listOf("apple", "banana", "kiwifruit")
for (index in items.indices) {
    println("item at $index is ${items[index]}")
}

while loop

val items = listOf("apple", "banana", "kiwifruit")
var index = 0
while (index < items.size) {
    println("item at $index is ${items[index]}")
    index++
}

when expression

fun describe(obj: Any): String =
    when (obj) {
        1          -> "One"
        "Hello"    -> "Greeting"
        is Long    -> "Long"
        !is String -> "Not a string"
        else       -> "Unknown"
    }

Java의 switch case 와 비슷한 것 같습니다.

Ranges

in 연산자를 사용하여 숫자가 범위 내에 있는지 확인합니다:

val x = 10
val y = 9
if (x in 1..y+1) {
    println("fits in range")
}

숫자가 범위 밖에 있는지 확인합니다:

val list = listOf("a", "b", "c")

if (-1 !in 0..list.lastIndex) {
    println("-1 is out of range")
}
if (list.size !in list.indices) {
    println("list size is out of valid list indices range, too")
}

범위에 걸쳐서 반복합니다:

for (x in 1..5) {
    print(x)
}

또는 건너뛰면서 반복합니다:

for (x in 1..10 step 2) {
    print(x)
}
println()
for (x in 9 downTo 0 step 3) {
    print(x)
}

Collections

컬렉션(collection)을 반복합니다:

for (item in items) {
    println(item)
}

Java의 Enhanced for loop 에 해당하는 것 같습니다.

컬렉션 내에 객체가 존재하는지를 in 연산자를 사용하여 확인합니다:

when {
    "orange" in items -> println("juicy")
    "apple" in items -> println("apple is fine too")
}

람다(lambda) 표현식을 사용하여 컬렉션을 필터링, 매핑합니다:

val fruits = listOf("banana", "avocado", "apple", "kiwifruit")
fruits
  .filter { it.startsWith("a") }
  .sortedBy { it }
  .map { it.toUpperCase() }
  .forEach { println(it) }

Java의 Stream 과 비슷해 보입니다.

Creating basic classes and their instances

val rectangle = Rectangle(5.0, 2.0)
val triangle = Triangle(3.0, 4.0, 5.0)

Java의 경우 new 키워드를 사용하여 인스턴스를 생성하는데 Kotlin은 그냥 생성할 수 있습니다.

정리하며

기존에 Java를 사용하는 입장에서 Kotlin이 상당히 매력적인 언어란 것을 다시금 느낄 수 있었습니다.

이번 파트를 학습하면서 함수 표현식의 지원, final 의 아쉬움을 채워주는 val 키워드, if 문이 아닌 식으로의 동작, null 반환 여부에 대한 명시적인 표현, 똑똑한 loop 지원 등을 배웠습니다. 이 내용들만으로도 Kotlin이 충분히 매력적인 언어임을 느낄 수 있었습니다.

제가 Kotlin Koans를 하면서 관련된 내용으로 Kotlin Reference를 학습하다 보니 Reference 순서대로 학습 내용을 올리지 못하는 점 양해 부탁드립니다 😢

참고 자료

Kotlin Reference - Basics / Basic Syntax

Kotlin - Basic Syntax(기본 구문) (1/2)

Kotlin - Basic Syntax(기본 구문) (2/2)

profile
growing up 🐥

0개의 댓글