본문 바로가기
프로그래밍/Kotlin

Kotlin 배우기 (1)

by 채연2 2024. 2. 1.

Contents

     

     

    슬럼프가 길어져 약 1년 정도를 블로그도 쉬고 개발도 쉬었던 것 같다. 전에 공부했던 내용은 다 잊어버렸기 때문에 다시 리프레쉬하는 마음으로 Kotlin을 처음부터 새로 공부하려고 한다. 

     

    Kotlin Basic Syntax (1)

    Kotlin 코틀린은 더 적은 코드와 가독성이 결합된 언어라고 한다. 그래서 보다 다른 개발자의 코드를 이해하기가 쉽다고 한다. google 내부 데이터에 따르면 Kotlin으로 구축된 앱은 충돌 가능성이 20% 적다는 결과가 있다. 또, 다중 플랫폼 개발을 지원한다는 장점도 있는 등 많은 이점이 있는 Kotlin 언어를 배워보려고 한다.

     

     

    Program entry point - 프로그램 진입점

    Kotlin에서의 program entry point인 main 함수는 아래와 같이 2가지 버전으로 사용할 수 있다.

    //인자를 받지 않는 main 함수
    fun main() {
        println("Hello world!")
    }
    
    //여러개의 String 인자를 받는 main 함수
    fun main(args: Array<String>) {
        println(args.contentToString())
    }

     

     

    Functions - 함수

    Kotlin에서의 파라미터 선언은 변수명: 타입과 같고, 리턴 타입은 마지막에 선언해준다.

    fun sum(a: Int, b: Int): Int {
        return a + b
    }
    
    fun main() {
        print("sum of 3 and 5 is ")		//sum of 3 and 5 is 8
        println(sum(3, 5))
    }

     

     

    함수 본문은 표현식이 될 수 있고, 리턴 타입은 유추된다.

    fun sum(a: Int, b: Int) = a + b
    
    fun main() {
        println("sum of 19 and 23 is ${sum(19, 23)}")	//sum of 19 and 23 is 42
    }

     

     

    리턴 값이 없으면 void 대신 Unit을 사용하고, Unit 타입은 생략 가능하다.

    fun printSum(a: Int, b: Int): Unit {
        println("sum of $a and $b is ${a + b}")
    }
    
    fun main() {
        printSum(-1, 8)		//sum of -1 and 8 is 7
    }
    
    //--------------------------------------------
    
    //Unit type 생략
    fun printSum(a: Int, b: Int) {
        println("sum of $a and $b is ${a + b}")
    }

     

     

    Variables - 변수

    읽기 전용 local 변수는 val 키워드를 사용하고, 값은 한 번만 할당될 수 있다. 유형 추론, 지연 할당도 가능하다.

    fun main() {
        val a: Int = 1
        val b = 2
        val c: Int
        c = 3
        println("a = $a, b = $b, c = $c")	a = 1, b = 2, c = 3
    }

     

     

    값을 여러 번 할당할 수 있는, 즉 재할당이 가능한 local 변수는 var 키워드를 사용한다.

    fun main() {
        var x = 5
        x += 1
        println("x = $x")	//x = 6
    }

     

     

    Class / Instances - 클래스 및 인스턴스

    Class 선언에 파라미터들을 정의할 수 있고, 자동으로 생성자를 사용할 수 있다.

    class Rectangle(val height: Double, val length: Double) {
        val perimeter = (height + length) * 2 
    }
    
    fun main() {
        val rectangle = Rectangle(5.0, 2.0)
        println("The perimeter is ${rectangle.perimeter}")  //The perimeter is 14.0
    }

     

     

    Class를 상속 가능하도록 하려면 open 키워드를 사용해서 선언해야 하고, 상속은 :(콜론)을 사용한다.

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

     

     

    Conditional Expressions - 조건식

    fun maxOf(a: Int, b: Int): Int {
        if (a > b) {
            return a
        } else {
            return b
        }
    }
    
    fun main() {
        println("max of 0 and 42 is ${maxOf(0, 42)}")	//max of 0 and 42 is 42
    }

     

     

    if문은 아래와 같이 표현식으로 사용할 수 있다.

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

     

     

    for loop - for문

    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]}")
    }
    
    /*item at 0 is apple
      item at 1 is banana
      item at 2 is kiwifruit*/

     

     

    while loop - while문

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

     

     

    when Expression - when 표현식

    약간 switch문과 비슷한 것 같다. describe 함수 인자로 어떤 값이든 받을 수 있고, 그 값이 해당하는 조건의 리턴 값을 출력한다.

    fun describe(obj: Any): String =
        when (obj) {
            1          -> "One"
            "Hello"    -> "Greeting"
            is Long    -> "Long"
            !is String -> "Not a string"
            else       -> "Unknown"
        }
    
    fun main() {
        println(describe(1))	//One
        println(describe("Hello"))	//Greeting
        println(describe(1000L))	//Long
        println(describe(2))	//Not a string
        println(describe("other"))	//Unknown
    }

     

     

    Ranges - 범위

    아래 코드는 in 연산자를 사용하여 x 값이 범위 안에 있는지 체크할 수 있다.

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

     

     

    ! 연산자를 사용하여 범위를 벗어났는지도 체크할 수 있다.

    fun main() {
        val list = listOf("a", "b", "c")
    
        if (-1 !in 0..list.lastIndex) {
            println("-1 is out of range")			//-1 is out of range
        }
        if (list.size !in list.indices) {
            println("${list.size} !in ${list.indices}")	//3 !in 0..2
        }
    }

     

     

    for문과 함께 범위 연산자를 사용할 수 있다.

    fun main() {
        for (x in 1..5) {
            print(x)	//12345
        }
    }

     

     

    step 키워드를 사용하여 원하는 만큼 건너뛸 수 있다.

    fun main() {
        for (x in 1..10 step 2) {
            print(x)	//13579
        }
        println()
        for (x in 9 downTo 0 step 3) {
            print(x)	//9630
        }
    }

     

     

    Collections - 컬렉션

    in 연산자를 사용해서 컬렉션 안에 해당 객체가 포함되어 있는지 확인할 수 있다.

    fun main() {
        val items = setOf("apple", "banana", "kiwifruit")
        when {
            "orange" in items -> println("juicy")
            "apple" in items -> println("apple is fine too")
        }	//apple is fine too
    }

     

     

    lambda 표현식을 사용해서 컬렉션을 필터링하고 매핑할 수 있다. 이때, 컬렉션의 객체는 it 키워드로 표기한다.

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

     

     

    Nullable values and null checks - Null 허용 값과 null 값 검사

    null 값이 가능한 경우 참조는 명시적으로 nullable로 표시되어야 한다. nullable로 표시하려면 타입 뒤에 ?를 넣어준다.

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

     

     

    nullable 값을 반환하는 함수는 아래 코드와 같이 사용할 수 있다.

    fun printProduct(arg1: String, arg2: String) {
        val x = parseInt(arg1)
        val y = parseInt(arg2)
    
        if (x != null && y != null) {
            println(x * y)
        }
        else {
            println("'$arg1' or '$arg2' is not a number")
        }    
    }

     

     

    Type checks and automatic casts - 타입 검사 및 자동 캐스팅

    is 연산자는 객체가 해당 타입이 맞는지 확인한다. 특정 타입에 대해 체크가 되면 이는 명시적으로 캐스팅할 필요가 없다. 하지만 체크가 되지 않으면 여전히 타입 추론이 불가하다.

    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는 is 연산자를 통해 String으로 자동 캐스팅되므로 && 뒤의 조건식을 수행할 수 있다.
        if (obj is String && obj.length > 0) {
            return obj.length
        }
    
        return null
    }

     

     

     

    320x100

    '프로그래밍 > Kotlin' 카테고리의 다른 글

    Kotlin 배우기 (3)  (0) 2024.02.13
    Kotlin 배우기 (2)  (1) 2024.02.01
    [Kotlin 기초 2] Objects (3)  (9) 2023.02.17
    [Kotlin 기초 2] Objects (2)  (6) 2023.02.09
    [Kotlin 기초 2] Objects (1)  (4) 2023.02.09

    댓글