Kotlin: Basic syntax

Kotlin: Basic syntax

최근에 기업 공고를 보면 java/kotlin 기반으로 spring boot를 사용할 줄 아는 사람들을 뽑는다는 글을 많이 봤다. 내가 지원한 기업에서도 질문으로 kotlin을 사용해봤냐는 질문이 있었기에 기본적인 공부는 해볼려고 한다. 여기를 보고 정리해놓을려고 한다.


이 글은 kotlin의 기본적인 syntax를 간략하게 적어놓은 해당 사이트를 보고 번역의 의미와 함께 공부를 위해 정리하는 글이다.


Program entry point

프로그램을 실행하는 부분은 main method이다.

fun main() {
    println("Hello Kotlin!")
}

기존에 Java에서는 public static void main(String[] args)와 같이 아주 길게도 적어줬어야 했는데 매우 간략해진 것을 볼 수 있다.

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

이렇게 args로도 입력을 받을 수 있다.


print("Hello Kotlin\n")
println("Hello Kotlin")
Hello Kotlin
Hello Kotlin

이걸 보면서 감격을 했다. System.out.println("Hello Java!")라고 출력할 문자보다 긴 코드를 적으면서 현타가 왔던 나에게 ‘이래도 되는거야…?’라는 기분을 느끼게 해줬다.

확실히 kotlin으로 넘어가는 이유 중 하나인

Java보디 더욱 간결한 코드

가 잘 드러나는 순간인 것 같다.


Functions

fun add(num1: Int, num2: Int): Int {
    return num1 + num2
}
fun add(num1: Int, num2: Int) = num1 + num2

이렇게 하면 return type이 알아서 추론된다고 한다.

fun add(num1: Int, num2: Int): Unit {
    println("$num1 + $num2 = ${num1 + num2}")
}

위와 같이 Unit으로 의미없는 value도 return할 수 있다고 한다.

Unit이 뭔데…?

The type with only one value: the Unit object. This type corresponds to the void type in Java.

Java에서의 void method랑 대응된다고 보면될 것 같다. 그리고 당연하게도 Unit은 아래와 같이 생략될 수 있다고 한다.

fun add(num1: Int, num2: Int) {
    println("$num1 + $num2 = ${num1 + num2}")
}

하지만 위와 같은 코드는 kotlin code convention #Function에 의하면 좋지 않은 스타일이라고 한다.

Prefer using an expression body for functions with the body consisting of a single expression.

따라서 고치면 아래와 같다.

fun add(num1: Int, num2: Int) = println("$num1 + $num2 = ${num1 + num2}")


Variables

Java와의 가장 이질감이 있다고 생각했던 부분이었다. 그 동안 항상 type을 명시해왔으나 이제는 추론하라고 하니…


Conditional expressions

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

해당 문법은 조금 익숙했다. 예전에 python을 공부했을 때 비슷한 문법이 있었기 때문이다.

## python code ##
a = 1
b = 4
max_number = a if a > b else b


for loop

val names = listOf("김재준", "김근우", "문명석")
for (name in names) {
    println("$name 는 동아리 회원입니다.")
}
val names = listOf("김민협", "류도연", "이찬희")
for (index in names.indices) {
    println("$index's member is $names[index]")
}

일단은 kotlin언어에 대하여 전반적으로 훑어보는 중이어서 나중에 깊게 볼 것이다. 하지만 for looppython에서 비슷한 문법이 존재했기에 익숙했다.


while loop

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

Java랑 똑같다.


when expression

fun describe(obj: Any): String =
    when (obj) {
        1 -> "this is 1"
        "Hello" -> " Kotlin!!"
        "xi-jjun" -> " : owner of this repo"
        else -> "Unknown"
    }

when… 진짜 생소했다. 왜냐하면 처음 들어보니깐! 눈치껏 보자면 Javaswitch를 표현하는 것 같았다. 하지만 Java보다 훨씬 간결해진 코드를 볼 수 있다. 기존 Java에서는

String describe(Object obj) {
    switch ...
}

이렇게 위의 kotlin code를 표현해볼 수 있을 것이다. 그러나 애초에 Java에서는 switch의 조건에 Any라는 타입을 넣을 수 없다…?

// Java code
String formatterPatternSwitch(Object o) {
    return switch (o) {
        case Integer i -> String.format("int %d", i);
        case Long l    -> String.format("long %d", l);
        case Double d  -> String.format("double %f", d);
        case String s  -> String.format("String %s", s);
        default        -> o.toString();
    };
}

??? 있다. Java SE 17에 생겼다고 한다.

설마해서 찾아봤는데 진짜 있을 줄은 몰랐다. 하지만 완전하게 같지는 않은 것 같아 보인다.

static void test(Object o) {
    switch (o) {
        case String s && (s.length() == 1) -> ...
        case String s                      -> ...
        ...
    }
}

하지만 또 이렇게 String s && (s.equals("SOME_STRING"))으로 case condition을 준다면 비슷해질지도 모르겠다. 재밌어 보이니 다음에 따로 정리해보도록 하겠다.


Ranges

val start = 1
val end = 4
for (number in start..end) {
    println(number)
}
1
2
3
4

Put spaces around binary operators (a + b). Exception: don’t put spaces around the “range to” operator (0..i).

code convention #whitespace를 보면 위와 같이 적혀 있다. 따라서 start..end사이에는 공백이 없어야 함을 주의하자.

println("1 to 10 by step 2")
for (x in 1..10 step 2) {
    print("${x} ")
}

println("\n5 to 2 by step 1")
for (x in 5 downTo 1) {
    print("${x} ")
}

println("\n7 to 1 by step 2")
for (x in 7 downTo 1 step 2) {
    print("${x} ")
}
1 to 10 by step 2
1 3 5 7 9 
5 to 2 by step 1
5 4 3 2 1 
7 to 1 by step 2
7 5 3 1 

Modern언어는 대부분 python도 마찬가지지만 비슷한 것 같다. 간결함과 직관성을 추구하다 보니 저렇게 된게 아닐까.


느낀점

swift와 비슷하다는 느낌을 많이 받았다. 그도 그럴게

// swift code
func hello(name: String) {
    print("Hello, \(name)!")
}
// kotlin code
fun hello(name: String) {
    print("Hello $name!")
}

비슷한 부분이 확실하게 많이 보인다. 비교적 최근에 만들어진 언어들은 비슷하다는 느낌인 것 같다. 그리고 ‘null 에 대한 안정성’에 대해서는 두 언어가 null check가 잘 된다는 점을 보면…

swift는 잠시 머리 식힐겸 한 것이라 익숙하게 다룬다고는 할 수 없다. 그러나 비슷한 부분이 많았기에 큰 어려움 없이 이해할 수 있는 부분들이 많았다. 꾸준히 공부하여 spring boot project도 모두 kotlin으로 바꿔볼 생각이다.


Next…

Collections, Nullable, Type check 등등이 남아있다. 이 3가지는 중요해보이기에 다음 포스팅에서 마저 정리하도록 하겠다.


Reference

kotlin docs:basic syntax

why kotlin? : Jetbrain

what is Unit in kotlin?

kotlin functions code convention

Java switch condition by any type

Kotlin whitespace code convention