개발지식

Kotlin 기본 구조(예시 코드)

우루쾅 2025. 8. 14. 07:31
728x90
반응형
SMALL

 

JAVA 를 베이스로 한 코틀린을 예시코드 통해 학습 해봅시다!

 

 

● 클래스 다형성

콜라 인스턴스를 음료 인스턴스에 담는 행위를 상위 자료형인 수퍼클래스로 변환한다고 하여 Up-Casting
Up-Casting을 다시 하위 자료형으로 변환하면 Down-Casting

fun main() {

    var a = Drink()
    a.drink()
    
    // 콜라 인스턴스를 음료 인스턴스에 담는 행위를 
    // 상위 자료형인 수퍼클래스로 변환한다고 하여
    // Up-Casting 이라고 함!
    var b : Drink = Cola()
    b.drink()
    
    // Up-Casting을 다시 하위 자료형으로 변환하면 Down-Casting 이라고 함
    // is 는 호환되는 자료형을 변환해주지만 조건문 내에서만 동작
    if(b is Cola){
        b.wachDishes()
    }
    
    // as 는 호환되는 자료형으로 변환해주는 캐스팅 연산자
    // 변환된 자료형을 반환까지 함
    var c = b as Cola
    c.wachDishes()
    // b가 되는 이유는 c에서 as로 이미 변환했기 때문에
    b.wachDishes()
}

// 클래스 다형성

open class Drink(){
    var name = "음료"
    
    open fun drink(){
        println("${name} 를 마십니다")
    }
}

class Cola : Drink(){
    var type = "콜라"

    override fun drink(){
        println("${name} 중에 ${type} 를 마십니다")
    }
    
    fun wachDishes(){
        println("${type} 로 설거지를 합니다")
    }
}

 

 

● Generic 함수

제네릭 함수/클래스는 타입을 미리 고정하지 않고, 호출 시 결정되는 타입을 그대로 가져와 사용하게 해주는 문법

fun main() {

    UsingGeneric(A()).doShouting()
    UsingGeneric(B()).doShouting()
    UsingGeneric(C()).doShouting()
    
}

fun <T : A> doShouting(t:T){
    t.shout()
}

open class A {
    open fun shout(){
        println("A가 소리칩니다.")
    }
}

class B : A(){
    override fun shout(){
        println("B가 소리칩니다.")
    }
}

class C : A(){
    override fun shout(){
        println("C가 소리칩니다.")
    }
}

class UsingGeneric<T : A> (val t : T){
    fun doShouting(){
        t.shout()
    }
}

 

 

 내부클래스

inner 클래스는 outer 클래스의 변수를 참조 가능
outer 클래스를 참조할 때에는 this@Outer 를 사용

fun main() {
    
    Outer.Nested().introduce()
    
    val outer = Outer()
    val inner = outer.Inner()
    
    inner.introduceInner()
    inner.introduceOuter()
    
    outer.text = "Changed Outer Class"
    inner.introduceOuter()
    
}

class Outer{
    var text = "Outer Class"
    
    class Nested{
        fun introduce(){
            println("안녕")
        }
    }
    
    // inner 클래스는 outer 클래스의 변수를 참조 가능
    inner class Inner{
        var text = "Inner Class"
        
        fun introduceInner(){
            println(text)
        }
        
        // outer 클래스를 참조할 때에는 this@Outer 를 사용
        fun introduceOuter(){
            println(this@Outer.text)
        }
    }
}

 

 

 data 클래스

data 클래스는 데이터를 처리하기에 더욱 용이한 클래스!

아래의 코드를 수행했을 때 값의 차이를 확인할 수 있다

fun main() {
    
    val a = General("보영",212)
    
    println(a == General("보영",212))
    println(a.hashCode())
    println(a)
    
    val b = Data("루다",306)
    
    println(b == Data("루다",306))
    println(b.hashCode())
    println(b)
    
    println(b.copy())
    println(b.copy("아린"))
    println(b.copy(id=316))
    
    // 리스트 형식으로도 열거할 수 있음
    val list = listOf(Data("보영",212),
                  Data("루다",306),
                  Data("아린",316)
                  )
    
    for((a, b) in list){
        println("${a} , ${b}")
    }
}

class General(val name:String, val id:Int)

data class Data(val name:String, val id:Int)

 

 

enum 클래스
enum 은 선언시 만든 객체를 이름으로 참조하여 그대로 사용

fun main() {
    
    // enum 은 선언시 만든 객체를 이름으로 참조하여 그대로 사용
    var state = State.SING
    println(state)
    
    state = State.SLEEP
    println(state.isSleeping())
    
    state = State.EAT
    println(state.message)
    
}

enum class State(val message:String){
    SING("노래를 부릅니다"),
    EAT("밥을 먹습니다"),
    SLEEP("잠");
    
    fun isSleeping() = this == State.SLEEP
}

 

 

Map 셋팅

Map 으로 key, value 를 저장하여 데이터를 가져오고 변경, 삭제가 가능

fun main() {
    
    val a = mutableMapOf("레드벨벳" to "음파음파", 
                        "트와이스" to "FANCY",
                        "ITZY" to "ICY")
	
    for (entry in a){
        println("${entry.key} : ${entry.value}")
    }
    
    a.put("오마이걸","번지")
    println(a)
    
    a.remove("ITZY")
    println(a)
    
    println(a["오마이걸"])
}

 

 

컬렉션 함수

fun main() {
    
    var nameList = listOf("박수영","김지수","김다현","신유나","김지우")
    
    // 리스트 for 문
    nameList.forEach{ print(it + " ") }
    println()
    
    // 시작 문자 확인
    println(nameList.filter{ it.startsWith("김") })
    
    // map 을 통해 리스트 조회
    println(nameList.map{"이름 : "+it})
    
    // 데이터 중 있으면 true / 없으면 false
    println(nameList.any{ it == "김지우" })
    
    // 전체 데이터가 맞으면 출력
    println(nameList.all{ it.length == 3 })
    
    // 아무도 없으면 true / 하나라도 있으면 false
    println(nameList.none{ it.startsWith("이") })
    
    // 조건이 맞는 첫번째 데이터 출력
    println(nameList.first{ it.startsWith("김") })
    
    // 조건이 맞는 마지막 데이터 출력
    println(nameList.last{ it.startsWith("김") })
    
    // 조건이 맞는 리스트 카운트 
    println(nameList.count{ it.contains("지") })
}

 

 

상수(companion)
늘 고정적인 값으로 사용할 때에는 상수를 통해 객체의 생성없이 메모리에 값을 고정하여 사용함으로써 성능을 향상시킬 수 있음

상수는 항상 대문자로 표기를 하여 상수라는 것을 누구나 알 수 있게끔 해야됨

fun main() {
    
    val foodCourt = FoodCourt()
    
    foodCourt.searchPrice(FoodCourt.FOOD_CREAM_PASTA)
    foodCourt.searchPrice(FoodCourt.FOOD_STEAK)
    foodCourt.searchPrice(FoodCourt.FOOD_PIZZA)
    
}

class FoodCourt{
    fun searchPrice(foodName: String){
        val price = when(foodName){
            FOOD_CREAM_PASTA -> 13000
            FOOD_STEAK -> 25000
            FOOD_PIZZA -> 15000
            else -> 0
        }
        
    	println("${foodName} 의 가격은 ${price} 입니다")
    }
    
    // 늘 고정적인 값으로 사용할 때에는 상수를 통해 객체의 생성없이
    // 메모리에 값을 고정하여 사용함으로써 성능을 향상시킬 수 있음
    companion object{
        const val FOOD_CREAM_PASTA = "크림파스타"
        const val FOOD_STEAK = "스테이크"
        const val FOOD_PIZZA = "피자"
    }
}

 

 

코루틴(Coloutin)

import kotlinx.coroutines.*

fun main() {
    
    // runBlocking 안의 모든 코루틴이 끝날 때까지
    // 현재 스레드를 블로킹(멈춤)
    runBlocking{
        // launch: 반환값 없이 코루틴 실행 (Job 반환)
        val a = launch{
            for(i in 1..5){
                println(i)
                delay(10)
            }
        }
        
        // async: 결과값을 반환하는 코루틴 실행 (Deferred<T> 반환)
        val b = async{
            "async 종료"
        }
        
        println("async 대기")
        // await(): Deferred에서 결과를 가져옴.
        // 결과가 준비될 때까지 현재 코루틴을 일시 중단
        println(b.await())
        
        // join(): Job이 끝날 때까지 현재 코루틴을 일시 중단
        a.join()
        println("launch 종료")
        
    }
}

 

 

 코루틴(Coloutin) - withTimeoutOrNull

withTimeoutOrNull(시간) 안에 함수가 종료되면 null 을 내뱉음

import kotlinx.coroutines.*

fun main() {
    
    runBlocking{
        var result = withTimeoutOrNull(50){
            for(i in 1..10){
                println(i)
                delay(10)
            }
            "Finish"
        }
        println(result)
    }
}

 

 

출처

코틀린 - https://play.kotlinlang.org/
디모의 Kotlin 강좌 - https://www.youtube.com/watch?v=8RIsukgeUVw&list=PLQdnHjXZyYadiw5aV3p6DwUdXV2bZuhlN&index=1&pp=iAQB

728x90
반응형
LIST