코틀린 스터디

코틀린 - 변수, 연산자, 반복문, 함수

막이86 2023. 11. 10. 15:48
728x90

Kotlin in Action 을 요약한 내용입니다.

변수

  • 변수 선언시 이름 뒤에 타입을 명시하거나 생략
  • 타입 지정을 생략하고 사용 가능
  • val javacafe = "자바카페" val number = 20 // 타입 지정하고 사용 가능 val number: Int = 20

변경 가능한 변수와 변경 불가능한 변수

  • val
    • 변경 불가능한 참조를 저장하는 변수
    • val로 선언된 변수는 초기하고 나면 재대입이 불가능
    • 자바에서 final
  • var
    • 변경 가능한 참조를 저장하는 변수
    • 자바의 일반 변수

<aside> 💡 기본적으로 모든 변수를 val 키워드를 사용해 불변 변수로 선언하고 필요할 때만 var로 변경

</aside>

  • val 참조 자체는 불변이라도 참조가 가르키는 값은 변경될 수 있다.
  • fun main() { val languages = arrayListOf("Java") languages.add("Kotlin") }
  • var 키워드를 사용하면 변수의 값을 변경할 수 있지만 변수의 타입은 고정되어 있음
  • fun main() { var answer = 42 answer = "no answer" } Type mismatch: inferred type is String but Int was expected

문자열 템플릿

  • 변수를 문자열 안에 사용 가능
  • fun main() { val name = "자바카페" println("Hello, $name") }
  • 복잡한 식도 중괄호로 둘러싸서 문자열 템플릿 안에 넣을 수 있다.
  • fun main() { val name = "자바카페" println("Hello, ${name.length}") }

기본 타입

범주 기본 타입

Integers Byte, Short, Int, Long
Unsigned Integers UByte, UShort, UInt, ULong
Floating-point Numbers Float, Double
Booleans Boolean
Characters Char
Strings String

연산자

산술 연산자 오버로딩

  • 자바의 경우 원시 타입에 대해서만 산술 연산자를 사용할 수 있다.
    • String에 대해 +연산자를 사용

이항 산술 연산 오버로딩

  • plus 함수에 operator 키워드를 사용
  • data class Point(val x: Int, val y: Int) { operator fun plus(other: Point): Point { return Point(x + other.x, y + other.y) } } fun main() { val p1 = Point(10, 20) val p2 = Point(30, 40) println(p1 + p2) // p1 + p2 -> p1.plus(p2) }
  • 연산자를 확장 함수로 정의
  • operator fun Point.plus(other: Point): Point { return Point(x + other.x, y + other.y) }
  • 다른 언어와 비교할 때 코틀린에서 오버로딩한 연산자를 정의하고 사용하기 더 쉽다
    • 연산자 우선순위는 언제나 표준 숫자 타입에 대한 연산자 우선순위와 같다
    • a + b * c는 곱샘이 항상 덧셈보다 먼저 수행
    식 함수 이름
    a * b times
    a / b div
    a % b mod → 1.1 부터 rem
    a + b plus
    a - b minus
  • 연산자를 정의할 때 두 피연산자가 같은 타입일 필요는 없다
  • operator fun Point.times(scale: Double): Point { return Point((x * scale).toInt(), (y * scale).toInt()) } fun main() { val p = Point(10, 20) println(p * 1.5) }
  • 연산자의 반환 타입이 꼭 두 피연산자 중 하나와 일치해야만 하는 것도 아니다
  • operator fun Char.times(count: Int): String { return toString().repeat(count) } fun main() { println('a' * 3) }

복합 대입 연산자 오버로딩

  • 연산자 오버로딩하면 코틀린은 + 연산자뿐 아니라 그와 관련 있는 연산자인 +=도 자동으로 함께 지원
  • data class Point(val x: Int, val y: Int) { operator fun plus(other: Point): Point { return Point(x + other.x, y + other.y) } } fun main() { var point = Point(1, 2) point += Point(3, 4) println(point) }

단항 연산자 오버로딩

  • 단항 연산자를 오버로딩하는 절차도 이항 연산자와 같다
  • operator fun Point.unaryMinus(): Point { return Point(-x, -y) } fun main() { val p = Point(10, 20) println(-p) }
  • 오버로딩할 수 있는 단항 산술 연산자식 함수 이름
    +a unaryPlus
    -a unaryMinus
    !a not
    ++a, a++ inc
    —a, a— dec

조건문

If

  • if 사용
  • fun main() { val d: Int val check = true if (check) { d = 1 } else { d = 2 } println(d) }
  • Kotlin에는 삼항연산자가 없음
  • fun main() { val a = 1 val b = 2 println(if (a > b) a else b) }

When

  • 여러 분기가 있는 조건식이 있는 경우에 사용
    • 자바의 switch 와 비슷
    fun main() {
    	val obj = "Hello"
    
        when (obj) {
            "1" -> println("One")
            "Hello" -> println("Greeting")
            else -> println("Unknown")
        }
    }
    
  • 표현식으로 사용 가능
  • fun main() { val obj = "Hello" val result = when (obj) { "1" -> "One" "Hello" -> "Greeting" else -> "Unknown" } println(result) }
  • Boolean 표현식으로 조건 사용 가능
  • fun main() { val temp = 18 val description = when { temp < 0 -> "very cold" temp < 10 -> "a bit cold" temp < 20 -> "warm" else -> "hot" } println(description) }

반복문

For

  • for (변수 in 범위)
  • fun main() { for (number in 1..5) { print(number) } }
  • 컬렉션으로 반복문 사용 가능
  • fun main() { val cakes = listOf("carrot", "cheese", "chocolate") for (cake in cakes) { println("Yummy, it's a $cake cake!") } }

While

  • while(조건)
  • fun main() { var cakesEaten = 0 while (cakesEaten < 3) { println("Eat a cake") cakesEaten++ } }
  • do {} while(조건)
  • fun main() { var cakesBaked = 0 do { println("Bake a cake") cakesBaked++ } while (cakesBaked < 3) }

함수

  • 함수를 선언할 때 fun 키워드를 사용
  • 파라미터 이름 뒤에 파라미터의 타입 사용
  • 함수를 최상위 수준에 정의 가능
    • 자바에서는 클래스 안에 함수를 넣어야 함
    fun sum(x: Int, y: Int): Int {
    	return x + y
    }
    
    fun main() {
        println(sum(1, 2))
    }
    

식이 본문인 함수

  • 함수를 간단하게 표현할 수 있다.
  • fun sum(x: Int, y: Int) = x + y

반환이 없는 함수

  • 값을 반환하지 않는 함수는 반환 유형을 선언하지 않아도 됨
  • fun sum(x: Int, y: Int) { println("$x + $y = ${x+y}") }

익명함수

  • 익명 함수는 이름이 생략된다는 점을 제외하면 일반 함수 선언과 매우 유사
  • fun (x: Int, y: Int): Int = x + y fun (x: Int, y: Int): Int { return x + y } fun (s: String): Int { return s.toIntOrNull() ?: 0 }
  • 매개 변수 형식은 컨텍스트에서 유추할 수 있는 경우 생략 가능
  • fun main() { val ints = arrayOf(-3, -2, -1, 0, 1, 2, 3) val filter = ints.filter(fun(item) = item > 0) println(filter) }

람다표현식

람다 식의 문법

  • 람다 식을 선언하기 위한 문법
    • 코틀린 람다 식은 항상 중괄호로 둘러싸여 있다.
    • 화살표가 인자 목록과 람다 본문을 구분
    • 람다 식을 변수에 저장 가능
    { x: Int, y: Int -> x + y }
    

it: 단일 매개변수의 암시적 이름

  • 매개 변수가 하나만 있는 경우
    • 매개 변수는 it으로 암시적으로 선언됨
    fun main() {
        val ints = arrayOf(-3, -2, -1, 0, 1, 2, 3)
        val filter = ints.filter { > 0 }
        println(filter)
    }
    

람다 식에서 값 반환

  • 명시적으로 값을 반환 가능
    • 마지막 식의 값이 암시적으로 반환
    fun main() {
        val ints = arrayOf(-3, -2, -1, 0, 1, 2, 3)
        val filter1 = ints.filter {
            val shouldFilter = it > 0
            shouldFilter
        }
        println(filter1)
        
        val filter2 = ints.filter {
            val shouldFilter = it > 0
            return@filter shouldFilter
        }
        println(filter2)
    }
    

사용되지 않는 변수에 대한 밑줄

  • 매개 변수를 사용하지 않는 경우 이름 대신 밑줄을 넣을 수 있다.
  • fun main() { val map = hashMapOf(1 to "x", 2 to "y", 3 to "z") map.forEach { (_, value) -> println("$value") } }

클로저(Closure)

  • 클로저는 상위 함수의 영역의 변수를 접근할 수 있는 함수
  • fun add(x: Int): (Int) -> Int { return fun(y: Int): Int{ return x + y } } fun main() { val func = add(10) val result = func(20) println(result) }
  • 람다식으로 생성한 익명함수도 클로저 함수
    • forEach 함수는 sum에 값을 저장
    • 자바에서는 final이였지만 코틀린에서는 final이 아님
    fun main() {
    	var sum = 0
    	ints.filter { it > 0 }.forEach {
    		sum += it
    	}
    	print(sum)
    }
    
728x90