App_Dev/Android : Kotlin

[ 앱 개발자 도전기 : 안드로이드_코틀린 ] 코틀린 기본 문법 훑어보기.-[1]

안다미로 : APP & Web3 & D.S 2024. 11. 12. 16:47

 

 

 

 

[ 앱 개발자 도전기 : 안드로이드_코틀린 ] 코틀린 기본 문법 훑어보기.-[1]

 


 

 

∇ 코틀린 기본 문법 훑어보기 - [1]

목  차

1. 변수
2. 자료형
3. 형 변환
4. 배열
5. 타입 추론
6. 함수

 

 


§ 세미콜론을 붙이지 않아도 됩니다.

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

 

 

§ 변수 선언시 파스칼, 카멜 표기법을 권장합니다.

 

파스칼 표기법 : ClassName

카멜 표기법 : className

 


 

Ⅰ. 변수 선언 방법


      

   * var  :  일반적으로 통용되는 변수,  언제든지 읽기-쓰기가 가능함.,  변수값 변경 가능.

    *  val  :   선언시에만 초기화 가능,  중간에 값을 변경할 수 없음.  -> Java의 final

                 ex) runtime을 할 시 변경되지 말아야 할 값은 안전하게 val로 선언하는 것이 좋습니다.

 

 

          ◎ 변수는 '선언 위치' 따라 두가지 이름으로 불립니다.

                   - 클래스에 선언된 변수 : Property(속성)

                   - Scope 내에 선언된 변수 : Local Variable ( 로컬(지역) 변수 )

 

 

          ◎ 코틀린은 기본 변수에서 null을 허용하지 않습니다.

 

                   - 고전적인 언어들은, 변수가 선언된 후 초기화 되지 않으면

                     기본 값으로 초기화 되거나 값이 할당되지 않았다는 표시로 null 값을 가지게 됩니다.

 

                  - 코틀린은 기본 변수에서 null을 허용하지 않고, 

                         + 변수에 값을 할당하지 않은채로 사용하게 되면 문법 에러를 표시하고

                           ++ 컴파일을 막아주므로

                                의도치 않은 코드의 동작이나 'null point exception' 등을 원천적으로 차단해준다는 장점이 있습니다.

fun main() {
    var a: Int = 123 //코틀린은 값 초기화 필수!
    println(a)
    println(main2())
}

 

                         + 변수에 값을 할당하는 것은 반드시 선언시에 할 필요는 없으며,

                                  변수를 참조하여 사용하기 전까지만 하면 됩니다.

fun main2() {
    var b: Int
    b = 123 //이렇게 초기화해도 된다
    println(b)
}

 

                         ++  변수에 값이 할당되지 않았다는 것을 하나의 정보로 사용하는 경우도 있음.  ( ? 활용 )

                                 

fun main() {
    var a:Int? = null	
}

             - > null을 허용하는 'nullable 변수' 로 선언 가능합니다.

            하지만, ' null pointer exception ' 발생할 수 있으므로 꼭 필요한 경우에 한해서 주의해서 사용해야합니다.

 


 

Ⅱ.  자료형.


 - 변수에서 사용할 수 있도록, 코틀린이 제공하는 기본 자료형은 자바와의 호환을 위해  ' 자바와 거의 동일 ' 합니다.

 

 

       ☆ 정수, 실수형.

         

	
fun main() {

    var intValue:Int = 1234
    var longValue:Long = 1234L //L을 붙여 더 큰 메모리를 사용하는 정수임을 표시
    var intValueByHex:Int = 0x1af //16진수
    var intValueByBin:Int = 0b //2진수 (binary 약자)
	
    //코틀린은 8진수 표기는 지원하지 않는다.



    var doubleValue:Double = 123.5 //실수는 소수점을 포함해 숫자를 쓰거나
    var doubleValueWithExp:Double = 123.5e10 //필요시 지수 표기법을 추가한다.
    var floatValue:Float = 123.5f //Float는 f를 붙인다.


	
}

          - > 코틀린은 내부적으로 문자열을 UTF-16 BE 방식을 사용합니다.

                     - > 따라서, 글자 하나하나 2byte의 메모리 공간을 사용합니다.

 

 

       ☆ 문자, 문자열.

           

	
fun main() {

    var charValue:Char = 'a'
    var koreanCharValue:Char = '가'
    var stringValue = "one line string test"
    var multiLineStringValue = """multiline
    string
    test"""
}

 

 

       ☆ 불리언값.

	
fun main() {
    var booleanValue:Boolean = true

}

 

 


Ⅲ. 형 변환.


 

    ※ 코틀린형-변환시 발생할 수 있는 오류를 막기위해서,

          다른 언어들이 지원하는 '암시적 형변환'은 지원하지 않습니다.

 

          ○ 명시적 형변환 : 변환될 자료형을 개발자가 직접 지정.

 

          ○ 암시적 형변환 : 변수를 할당할 시 자료형을 지정하지 않아도 자동으로 형변환 됩니다.

 

 

 

  ※기본타입 형-변환 함수.

 

기본타입 형변환 함수 정리

val intValue: Int = 10
val longValue: Long = intValue.toLong()

val doubleValue: Double = 3.14
val floatValue: Float = doubleValue.toFloat()

val stringValue: String = "100"
val parsedInt: Int = stringValue.toInt()
package com.example.testapplication.test


fun main() {
    var a: Int = 54321
    var b: Long = a.toLong() //int를 long형으로 변환
    println(a)
    println(b)

    typeCheck(a)
    typeCheck(b)

}

fun typeCheck(obj:Any):Int?{ //Any는 모든 타입의 부모격이다
    //is 키워드는 객체 타입을 체크합니다.
    if(obj is String){
        println("String 입니다.")
    }else if(obj is Int){
        println("Int 입니다.")
    }else {
        println("그 이외의 타입입니다.")
    }

    return null
}

 

 

 

  ※문자열 형-변환 함수.

         : 문자열을 숫자 타입으로 변환할 때는 다음과 같은 함수들을 활용.

           -변환 실패 시 null값을 반환하므로, 안전한 형-변환이 가능합니다.

 

val str = "100"
val number = str.toIntOrNull() ?: 0

 

 

  ※객체 형변환

      : 객체의 형변환에는  'as' 키워드를 사용합니다.

val obj: Any = "Hello"
val str: String = obj as String

 

     + 안전한 형변환을 위해서 'as?' 를 사용할 수도 있습니다.

 

 

  ※스마트 캐스트.

        : 타입 검사 후 자동으로 형변환이 이루어집니다.

val obj: Any = "Hello"
if (obj is String) {
    println(obj.length) // obj가 자동으로 String으로 캐스팅됨
}

 

 


Ⅳ. 배열.


 

    ※ 코틀린의 배열은 고정된 크기를 가지고 있는 데이터 구조로,

        동일한 타입의 요소들을 순차적으로 저장합니다.

 

         [ == 한번 선언하고 나면, 전체 크기를 변경할 수 없다는 단점이 있지만, 

                 한번 선언하면 다른 자료구조보다 빠른 입출력이 가능해진다는 장점 ! ]

 

 

     ∇ 배열 생성.

          : 코틀린에서는 여러 가지 방법으로 배열을 생성 가능합니다.

            

              1. arrayOf() 함수 사용. !

val numbers = arrayOf(1, 2, 3, 4, 5)
val mixedArray = arrayOf(1, "two", 3.0, true)

 

 

              2. Array 생성자 사용. !

val squareNumbers = Array(5) { i -> i * i }

 

 

              3. 특정 타입의 배열 생성

 

val intArray = IntArray(5)
val charArray = CharArray(3) { 'a' }

 

 

             § 배열 접근 및 수정.

val fruits = arrayOf("Apple", "Banana", "Cherry")
println(fruits[0]) // "Apple" 출력
fruits[1] = "Blueberry"

 

 

             § 배열 순회

val numbers = arrayOf(1, 2, 3, 4, 5)

// for 루프 사용
for (number in numbers) {
    println(number)
}

// 인덱스를 사용한 순회
for (i in numbers.indices) {
    println("Index $i: ${numbers[i]}")
}

// withIndex() 사용
for ((index, value) in numbers.withIndex()) {
    println("Index $index: $value")
}

 

 

             § 유용한 배열 함수.

val numbers = arrayOf(1, 2, 3, 4, 5)

println(numbers.size) // 배열의 크기
println(numbers.sum()) // 모든 요소의 합
println(numbers.average()) // 평균값
println(numbers.max()) // 최대값
println(numbers.min()) // 최소값

 

 

             § 다차원 배열

val matrix = Array(3) { IntArray(3) }

 

package com.example.testapplication.test

fun main() {
    // 1. arrayOf() 함수를 사용한 배열 생성
    val numbers = arrayOf(1, 2, 3, 4, 5)
    println("numbers: ${numbers.contentToString()}")

    println("--------")

    // 2. Array 생성자를 사용한 배열 생성
    val squareNumbers = Array(5) { i -> i * i }
    println("squareNumbers: ${squareNumbers.contentToString()}")

    println("--------")

    // 3. 특정 타입의 배열 생성
    val intArray = IntArray(5) { it * 2 }
    println("intArray: ${intArray.contentToString()}")

    println("--------")

    // 4. 문자 배열 생성
    val charArray = CharArray(3) { 'a' + it }
    println("charArray: ${charArray.contentToString()}")

    println("--------")

    // 5. 2차원 배열 생성 및 출력
    val matrix = Array(3) { IntArray(3) { it } }
    println("matrix:")
    for (row in matrix) {
        println(row.contentToString())
    }

    println("--------")

    // 6. 배열 요소 접근 및 수정
    val fruits = arrayOf("Apple", "Banana", "Cherry")
    println("Original fruits: ${fruits.contentToString()}")
    fruits[1] = "Blueberry"
    println("Modified fruits: ${fruits.contentToString()}")


    println("--------")


    // 7. 배열 순회 및 출력
    println("Fruits:")
    for ((index, fruit) in fruits.withIndex()) {
        println("Index $index: $fruit")
    }

    println("--------")

    // 8. 배열 함수 사용
    println("Sum of numbers: ${numbers.sum()}")
    println("Average of numbers: ${numbers.average()}")
    println("Max of numbers: ${numbers.max()}")
    println("Min of numbers: ${numbers.min()}")
}

 

  ☆ 배열의 특징.

 

            1. 코틀린의 배열은 불변(immutable)이 아닙니다.  요소의 값을 변경할 수 있습니다.

 

            2. 배열의 크기는 생성 시점에 고정되며, 이후에 변경할 수 없습니다.

 

            3. 코틀린은 기본 타입(int, long, Double 등)에 대한

                 특별한 배열 클래스(IntArray, LongArray, DoubleArray 등)를제공합니다. 

                 이들은 자바의 기본 타입 배열과 동일하게 동작하여, 성능상 이점이 있음.

 

            4. Array<T> 생성자를 사용하면, 람다식을 통해 초기값을 설정할 수 있습니다.

 

 

- 코틀린의 배열은 자바의 배열과 유사하지만, 더 안전하고 편리한 기능들을 제공합니다.

- 특히 코틀린의 컬렉션 함수들과 함께 사용하면 배열을 더욱 효과적으로 다룰 수 있습니다.

 

 


 

Ⅴ. 타입 추론.


 

※ 코틀린의 타입 추론(Type inference)은 변수나 함수의 타입을 명시적으로 선언하지 않더라도

       컴파일러가 자동으로 타입을 추론하는 기능입니다.

        [ 코드를 더 간결하게 만들어주면서도 정적-타입 언어의 안전성을 유지할 수 있도록 해줍니다.]

 

 

     ☆ 타입 추론의 주요 특징.

 

          1. 변수 선언 시 타입 추론 :

val name = "John" // String으로 추론
val age = 30 // Int로 추론
val pi = 3.14 // Double로 추론

 

 

          2. 함수 반환 타입 추론 :

fun add(a: Int, b: Int) = a + b // Int로 추론

 

 

          3. 컬렉션의 타입 추론 :

val numbers = listOf(1, 2, 3) // List<Int>로 추론
val names = setOf("Alice", "Bob") // Set<String>으로 추론

 

 

          4. 람다 표현식의 타입 추론 :

val sum = { x: Int, y: Int -> x + y } // (Int, Int) -> Int로 추론

 

 

  ☆ 타입 추론의 장점.

 

            1.  코드 간결성 : 타입을 명시적으로 작성하지 않아도 되므로, 코드가 더 간결.

 

            2. 가독성 향상 : 불필요한 타입 선언이 줄어들어서, 코드의 핵심 로직에 집중 가능.

 

            3. 생산성 증강 : 타입을 일일히 명시하지 않아도 되므로, 개발 속도가 향상.

 

            4. 유연성 : 타입이 변경되더라도 코드 수정이 최소화.

 

 

 

  ☆ 주의사항.

 

           1. 명시적 타입 선언이 필요한 경우 

                : 때로는 명시적으로 타입을 선언하는 것이 코드의 의도를 더 명확히 할 수도 있음.

 

          2. 복잡한 제네릭 타입

               : 복잡한 제네릭 타입의 경우에는 컴파일러가 정확히 추론하지 못할 수 있으므로,

                      명시적 선언이 필요할 수 있습니다.

 

         3. 가독성 고려

                : 때로는 타입을 명시하는 것이 코드의 의도를 더 명확히 전달 가능합니다.

 

 

    * 코틀린의 타입 추론은, 정적 타입 언어의 안정성을 유지하면서도 동적 타입 언어의 간결함을 제공합니다.

           -> 이는 코드를 더 읽기 쉽고 유지보수하기 쉽도록 만들어줍니다.

 


Ⅵ. 함수.


 

    ※ 함수 : 특정한 동작을 하거나 원하는 결과값을 연산하는데 사용합니다.

 

        

         ※ 함수 정의

              : 코틀린에서 함수는 'fun'  키워드를 사용하여 정의합니다.

fun functionName(parameter1: Type1, parameter2: Type2): ReturnType {
    // 함수 본문
    return result
}

 

	
fun main() {
	println(add(5, 6, 7))
}


	
fun add(a: Int, b: Int, c:Int): Int {
    return a + b + c
    //리턴 발생 시 함수 중간이더라도 함수 종료

}

-.> 실행 결과 : 18

 

    * 단일 표현식 함수로 위 코드를 변형하면, 변수에 결과값을 할당하듯 기술할 수 있도록 합니다.

	
fun main() {
	println(add(5, 6, 7))
}

fun add(a: Int, b: Int, c: Int) = a + b + c

       - 단일 표현식 함수는 반환형의 타입 추론이 가능하므로, 반환형을 생략 가능.

 

 

 

         ※ 함수의 주요 특징.

 

                 1. 반환 타입 추론 :

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

                   - 단일 표현식 함수의 경우, 반환 타입을 생략 가능 !

 

 

                 2. 기본 매개변수 :

fun greet(name: String = "Guest") = "Hello, $name!"

                   - 매개변수에 기본값을 지정할 수 있습니다.

 

 

 

                 3. 네임드 매개변수 :

fun createUser(name: String, age: Int) = User(name, age)
val user = createUser(age = 25, name = "John")

                   - 함수 호출 시 매개변수 이름을 명시할 수 있습니다.

 

 

 

                 4. 가변 인자 :

fun sum(vararg numbers: Int): Int = numbers.sum()

                   - 'vararg' 키워드를 사용하여, 가변 개수의 인자를 받을 수 있습니다.

 

 

                 5. 지역 함수 :

fun outer() {
    fun inner() {
        println("Inner function")
    }
    inner()
}

                   - 함수 내부에 다른 함수를 정의할 수 있습니다.

 

 

 

                 6. 확장 함수 :

fun String.double(): String = this.repeat(2)

                   - 기존 클래스에 새로운 함수를 추가할 수 있습니다.

 

 

 

                 7. 중위 함수 :

infix fun Int.plus(other: Int) = this + other
val result = 1 plus 2

                   - ' infix' 키워드를 사용하여, 중위 표기법으로 호출할 수 있는 함수를 정의할 수 있습니다.

 

 

                 8. 최상위 함수

                       : 코틀린에서는 함수를 클래스 외부에, 최상위 레벨로 정의 가능합니다.

 

                 9. 함수 타입

                       : 코틀린에서는 함수를 변수에 할당하거나, 다른 함수의 매개변수로 전달 가능합니다.

 

                 10. 최상위 함수

                       : 코틀린에서는 함수를 클래스 외부에, 최상위 레벨로 정의 가능합니다.

fun main() {
    // 1. 기본 함수 정의와 호출
    println("Sum: ${sum(5, 3)}")

    // 2. 반환 타입 추론
    println("Multiply: ${multiply(4, 7)}")

    // 3. 기본 매개변수
    greet()
    greet("Alice")

    // 4. 네임드 매개변수
    createUser(age = 30, name = "Bob")

    // 5. 가변 인자
    println("Sum of numbers: ${sumAll(1, 2, 3, 4, 5)}")

    // 6. 지역 함수
    outerFunction()

    // 7. 확장 함수
    val str = "Hello"
    println("Doubled string: ${str.double()}")

    // 8. 중위 함수
    println("Infix function result: ${5 plus 3}")

    // 9. 함수 타입
    val operation: (Int, Int) -> Int = ::sum
    println("Function type result: ${operation(10, 20)}")

    // 10. 꼬리 재귀 함수
    println("Factorial of 5: ${factorial(5)}")
}



// 1. 기본 함수
fun sum(a: Int, b: Int): Int {
    return a + b
}

// 2. 반환 타입 추론
fun multiply(a: Int, b: Int) = a * b

// 3. 기본 매개변수
fun greet(name: String = "Guest") {
    println("Hello, $name!")
}

// 4. 네임드 매개변수
fun createUser(name: String, age: Int) {
    println("Created user: $name, age: $age")
}

// 5. 가변 인자
fun sumAll(vararg numbers: Int): Int {
    return numbers.sum()
}

// 6. 지역 함수
fun outerFunction() {
    fun innerFunction() {
        println("This is an inner function")
    }
    innerFunction()
}

// 7. 확장 함수
fun String.double(): String {
    return this.repeat(2)
}

// 8. 중위 함수
infix fun Int.plus(other: Int): Int {
    return this + other
}

// 9. 함수 타입 (이미 sum 함수로 정의됨)

// 10. 꼬리 재귀 함수
tailrec fun factorial(n: Int, accumulator: Int = 1): Int {
    return when (n) {
        0, 1 -> accumulator
        else -> factorial(n - 1, n * accumulator)
    }
}