Kotlin v1.6.10 : Basic syntax

Basic syntax

번역문서 작성일 기준 Last modified: 13 September 2021
작성완료일 20220217


이것은 예제를 포함한 기본 문법 요소이다. 각 섹션의 마지막에서 관련된 토픽을 자세히 기술하는 링크를 찾을 수 있다.

JetBrains Academy의 무료 Kotlin Basics track에서 코틀린의 핵심적인 내용을 배울 수 있다.


Package definition and imports


패키지 지정은 반드시 소스 파일의 가장 위에 위치해야 한다.

package my.demo

import kotlin.text.*

//...

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

Packages를 보자.


Program entry point


Kotlin application의 entry point는 main function이다.

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

main 의 다른 형식은 다수의 String 아규먼트를 허용한다.

fun main(args: Array<String>) {
    println(args.contentToString())
}

Print to the standard output


print는 아규먼트를 standard output로 프린트한다.

print("Hello ")
print("world!")

//Hello world!

println은 아규먼트를 프린트하고 줄바꿈을 추가한다. 따라서 다른 것을 출력하면 그것은 다음 줄에 나타난다.

println("Hello world!")
println(42)

// Hello world!
// 42

Functions


다음 함수는 두 Int 파라미터와 Int 리턴 타입을 가진다.

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

function body는 표현식이 될 수 있으며, 이 함수의 리턴 타입은 추론된다.

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

어떤 의미있는 값도 반환하지 않는 함수

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}")
}

Functions를 보자.


Variables


읽기 전용 로컬 변수는 키워드 val을 사용해 정의된다. 그것들에는 오직 한 번만 값(value)가 할당될 수 있다.

val a: Int = 1 // 즉각적인 할당
val b = 2 // Int 타입이 추론된다
val c: Int // 초기화가 없다면 타입이 반드시 필요하다
c = 3 // 지연 할당

재할당 가능한 변수는 var 키워드를 사용한다.

var x = 5 // Int 타입이 추론된다
x += 1

top level에서 변수를 선언할 수 있다.

val PI = 3.14
var x = 0

fun increment(x) {
    x += 1
}

Properties를 함께 보자.


Creating classes and instances


클래스를 정의하기 위해 class 키워드를 사용한다.

class Shape

클래스의 프로퍼티는 선언이나 바디에 리스트될 수 있다.

class Rectangle(var height: Double, var length: Double) {
    var perimeter = (height + length) * 2 
}

클래스 선언에서 나열된 파라미터를 가진 기본 생성자는 자동으로 접근가능(available)하다.

val rectangle = Rectangle(5.0, 2.0)
println("the perimeter is ${rectangle.perimeter}")

클래스 간 상속은 콜론(:)으로 선언된다. 클래스는 기본적으로 final이다. 이것을 상속가능하게 하려면 open으로 만들어야 한다.

open class Shape

class Rectangle(var height: Double, var length: Double): Shape() {
    var perimeter = (height + length) * 2 
}

classesobjects and instances를 보자.


Comments


대부분의 현대 언어와 같이, 코틀린은 한 줄(single-line. 또는 end-of-line) 그리고 여러 줄(multi-line. block) 주석을 지원한다.

// end-of-line 주석이다.

/* 이것이
여러 줄
주석이다 */

코틀린에서 블록 주석은 중첩될 수 있다.

/* 주석이 여기서 시작되어서
/* 중첩된 주석을 가지고 */
여기서 끝난다. */

Documentation comment syntax에 대한 정보는 Documenting Kotlin Code를 보자.


String templates


var a = 1
// 템플릿 내 단순한 이름
val s1 = "a is $a"

a = 2
// 템플릿 내 임의 표현식(arbitrary expression)
val s2 = "${sl.replace("is", "was")}, but now is $a"

자세한 내용은 String templates를 보자.


Conditional expressions


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

코틀린에서는 if 또한 표현식으로 사용가능하다.

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

if-expressions를 보자.


for loop


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

또는

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

for loop를 보자.


while loop


val items = listOf("apple", "banana", "kiwifruit")
var index = 0

while (index < items.size) {
    println("item at $index is ${items[index]}")
    index++
}

while loop를 보자.


when expression


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

when expression를 보자.


Ranges


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")
}

범위를 순회(Iterate)하자.

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

또는 진행을 뛰어넘자(over a progression).

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

Ranges and progressions를 보자.


Collections


컬렉션을 순회한다.

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

in 오퍼레이터를 사용해 컬렉션이 오브젝트를 포함하고 있는지 확인한다.

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

컬렉션에 맵과 필터를 사용하기 위해 람다 표현식을 쓴다.

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

Collections overview를 보자.


Nullable values and null checks


null 값이 가능할 경우 참조는 반드시 명시적으로 nullable로 표시되어야 한다. nullable 타입은 마지막에 ?를 가진다.

다음은 str가 정수(integer)를 가지고 있지 않다면 null을 반환한다.

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

nullable 값을 반환하는 함수를 사용한다.

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

    // `x * y` 사용은 오류를 만든다. null일 수 있기 때문이다.
    if (x != null && y != null) {
        // x와 y는 널 체크 이후에 자동으로 non-nullable로 캐스팅된다.
        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와 y는 널 체크 후에 자동으로 non-nullable로 캐스트된다.
println(x * y)

Null-safety를 보자.


Type checks and automatic casts


is 오퍼레이터는 한 표현식이 특정 타입의 인스턴스인지 체크한다. 만약 불변 지역 변수(immutable local variable) 또는 프로퍼티가 특정 타입으로 체크된다면, 그것들은 명시적으로 캐스트될 필요가 없다.

fun getStringLength(obj: Any): Int? {
    
    if (obj is String) {
        // obj는 이 브랜치에서 자동으로 String으로 캐스트된다.
        return obj.length
    }

    // obj는 타입 체크된 브랜치 밖에서는 여전히 Any 타입이다.
    return null
}

또는

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

    // obj는 이 브랜치에서 자동으로 String으로 캐스트된다.
    return obj.length
}

심지어

fun getStringLength(obj: Any): Int? {

    // obj는 && 오른쪽에서 자동으로 String으로 캐스트된다.
    if (obj is String && obj.length > 0) {
        return obj.length
    }
    
    return null 
}

ClassesType casts를 보자.

좋은 웹페이지 즐겨찾기