MOBILE PROGRAMING

[모바일 프로그램밍] 코틀린(Kotlin)이란? ( 2 )

ch010104 2025. 9. 15. 22:15

1. 기초 타입 배열 (Primitive Type Arrays)

  • 코틀린에서는 기초 타입의 배열을 더 효율적으로 다루기 위해 전용 배열 클래스를 제공

기초 타입 배열 클래스

  • BooleanArray, ByteArray, CharArray
  • DoubleArray, FloatArray, IntArray
  • LongArray, ShortArray
 
val data1: IntArray = IntArray(3, { 0 })
val data2: BooleanArray = BooleanArray(3, { false })

 

arrayOf() 함수를 활용한 배열 생성

  • 값을 직접 할당하면서 배열을 생성할 수 있음
 
// 기본 arrayOf() 함수
val data = arrayOf<Int>(10, 20, 30)

// 기초 타입 전용 함수들
val data1 = intArrayOf(10, 20, 30)
val data2 = booleanArrayOf(true, false, true)

2. 컬렉션 타입 (Collection Types)

List, Set, Map의 특징

  • List: 순서가 있는 데이터 집합, 중복 허용
  • Set: 순서가 없는 데이터 집합, 중복 불허용
  • Map: 키-값 쌍의 데이터 집합, 키의 중복 불허용

가변 vs 불변 컬렉션

구분 타입 함수 특징
List List listOf() 불변
  MutableList mutableListOf() 가변
Set Set setOf() 불변
  MutableSet mutableSetOf() 가변
Map Map mapOf() 불변
  MutableMap mutableMapOf() 가변
// List 예제
var list = listOf<Int>(10, 20, 30)
var mutableList = mutableListOf<Int>(10, 20, 30)
mutableList.add(3, 40)
mutableList.set(0, 50)

// Map 예제 - Pair 객체와 'to' 키워드 사용
var map = mapOf<String, String>(Pair("one", "hello"), "two" to "world")

3. 조건문과 반복문

if-else 표현식

  • 코틀린의 if-else는 표현식으로 사용 가능하여 결괏값을 반환
 
val result = if (data > 0) {
    println("data > 0")
    true  // 각 블록의 마지막 줄이 반환값
} else {
    println("data <= 0")
    false
}

 

when 조건문

  • Java의 switch문보다 강력한 기능을 제공
 
when (data) {
    10 -> println("data is 10")
    20 -> println("data is 20")
    else -> println("data is not valid data")
}

// 다양한 조건 타입 지원
when (data) {
    is String -> println("data is String")
    20, 30 -> println("data is 20 or 30")
    in 1..10 -> println("data is 1..10")
    else -> println("data is not valid")
}

 

for 반복문

  • 다양한 범위 연산자를 활용할 수 있음
 
// 기본 범위
for (i in 1..10) { }           // 1부터 10까지 1씩 증가
for (i in 1 until 10) { }      // 1부터 9까지 1씩 증가 (10 미포함)
for (i in 2..10 step 2) { }    // 2부터 10까지 2씩 증가
for (i in 10 downTo 1) { }     // 10부터 1까지 1씩 감소

// 컬렉션 순회
for (i in data.indices) { }               // 인덱스로 순회
for ((index, value) in data.withIndex()) { } // 인덱스와 값 함께 순회

4. 클래스와 생성자

클래스 기본 구조

class User {
    var name = "kkang"
    constructor(name: String) {
        this.name = name
    }
    fun someFun() {
        println("name : $name")
    }
}

 

주 생성자 (Primary Constructor)

  • 클래스 선언부에 constructor 키워드로 선언
  • constructor 키워드 생략 가능
  • 한 클래스에 하나만 가능
 
// constructor 키워드 생략 가능
class User(name: String, count: Int) {
    init {
        println("i am init....")  // 객체 생성 시 자동 실행
    }
}

 

생성자 매개변수를 멤버 변수로 선언

class User(val name: String, val count: Int) {
    fun someFun() {
        println("name : $name, count : $count")  // 접근 가능
    }
}

 

보조 생성자 (Secondary Constructor)

  • 클래스 본문에 constructor 키워드로 선언
  • 여러 개 추가 가능
  • 주 생성자가 있다면 this() 구문으로 주 생성자 호출 필요
 
class User(name: String) {
    constructor(name: String, count: Int): this(name) {
        // 보조 생성자 본문
    }
}

5. 상속 (Inheritance)

상속 기본 문법

// 상속 가능하게 하려면 open 키워드 필요
open class Super(name: String) {
    
}

// 상속 시 상위 클래스 생성자 호출
class Sub(name: String): Super(name) {
    
}

 

오버라이딩 (Override)

  • 상위 클래스의 멤버를 하위 클래스에서 재정의
 
open class Super {
    open var someData = 10  // 오버라이딩 가능하게 open 키워드 필요
    open fun someFun() {
        println("i am super class function : $someData")
    }
}

class Sub: Super() {
    override var someData = 20  // override 키워드 필수
    override fun someFun() {
        println("i am sub class function : $someData")
    }
}

 

접근 제한자

접근 제한자 최상위에서 이용 클래스 멤버에서 이용
public 모든 파일에서 가능 모든 클래스에서 가능
internal 같은 모듈 내에서 가능 같은 모듈 내에서 가능
protected 사용 불가 상속 관계의 하위 클래스에서만 가능
private 파일 내부에서만 이용 클래스 내부에서만 이용

6. 코틀린의 특별한 클래스

데이터 클래스 (Data Class)

  • data 키워드로 선언하여 VO 클래스를 편리하게 이용:
 
data class DataClass(val name: String, val email: String, val age: Int)

// 자동으로 equals(), toString() 함수 제공
val data1 = DataClass("kkang", "a@a.com", 10)
val data2 = DataClass("kkang", "a@a.com", 10)
println(data1.equals(data2))  // true

 

오브젝트 클래스 (Object Class)

  • 익명 클래스 생성을 위해 사용:
 
val obj = object {
    var data = 10
    fun some() {
        println("data : $data")
    }
}

// 상위 클래스나 인터페이스 지정 가능
val obj = object: Super() {
    override var data = 20
    override fun some() {
        println("i am object some() : $data")
    }
}

 

컴패니언 클래스 (Companion Class)

  • 클래스 이름으로 멤버에 접근하고자 할 때 사용:
 
class MyClass {
    companion object {
        var data = 10
        fun some() {
            println(data)
        }
    }
}

// 사용 예
MyClass.data = 20
MyClass.some()

7. 람다 함수와 고차함수

람다 함수 기본 문법

  • 익명 함수를 간결하게 정의하는 방법:
 
// 기본 형태: { 매개변수 -> 함수 본문 }
val sum = {no1: Int, no2: Int -> no1 + no2}

// 매개변수가 없는 경우
{-> println("function call")}
{println("function call")}  // 화살표 생략 가능

// 매개변수가 1개인 경우 it 키워드 사용 가능
val some: (Int) -> Unit = {println(it)}

 

함수 타입과 고차 함수

// 함수 타입 선언
val some: (Int, Int) -> Int = { no1: Int, no2: Int -> no1 + no2 }

// 타입 별칭 사용
typealias MyFunType = (Int, Int) -> Boolean

// 고차 함수: 함수를 매개변수로 받는 함수
fun hofFun(arg: (Int) -> Boolean): () -> String {
    val result = if(arg(10)) {
        "valid"
    } else {
        "invalid"
    }
    return {"hofFun result : $result"}
}

8. 널 안전성 (Null Safety)

  • 코틀린의 가장 중요한 특징 중 하나로, 널 포인터 예외를 방지

널 허용과 불허용

var data1: String = "kkang"
// data1 = null  // 오류! 널 불허용

var data2: String? = "kkang"
data2 = null  // 성공! 널 허용

 

널 안전성 연산자

  • 안전 호출 연산자 (?.)
var data: String? = "kkang"
var length = data?.length  // data가 null이면 null 반환, 아니면 length 반환
  • 엘비스 연산자 (?:)
 
var data: String? = "kkang"
println("data = $data : ${data?.length ?: -1}")
// data가 null일 경우 -1 반환, 아니면 data.length 반환
  • 예외 발생 연산자 (!!)
 
fun some(data: String?): Int {
    return data!!.length  // data가 null이면 예외 발생
}