개발지식

Kotlin 기본 함수(예시 코드)

우루쾅 2025. 8. 12. 22:49
728x90
반응형
SMALL

 

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

 

 

● 스코프

스코프(scope)란 변수나 함수, 클래스 같은 멤버들을 서로 공유하여 사용할 수 있는 범위를 지정되는 단위

 

○ 패키지 스코프
public - 어떤 패키지에서도 접근 가능
internal - 같은 모듈 내에서만 접근 가능
private - 같은 파일 내에서만 접근 가능
protected 는 패키지 스코프에서 사용 X

 

클래스 스코프
public - 클래스 외부에서도 접근 가능
private - 클래스 내부에서만 접근 가능
protected - 클래스 자신과 상속받은 클래스에서 접근 가능
internal은 클래스 스코프에서 사용 X

// 스코프(scope)란 변수나 함수, 클래스 같은 멤버들을
// 서로 공유하여 사용할 수 있는 범위를 지정되는 단위
// 범위 : 패키지, 클래스, 함수

// 규칙 1 - 스코프 외부에서는 스코프 내부의 멤버를 참조연산자로만 참조가 가능
// 규칙 2 - 동일 스코프 내에서는 멤버들을 공유 가능
// 규칙 3 - 하위 스코프에서는 상위 스코프의 멤버를 재정의 가능하위 스코프에서는 상위 스코프의 멤버를 재정의 가능

val a = "패키지 스코프"

class B{
    val a = "클래스 스코프"
    fun print(){
        println(a)
    }
}

fun main() {
    val a = "함수 스코프"
    println(a)
    B().print()
}

 

  고차함수
클래스에서 만들어낸 인스턴스처럼 취급하는 방법, 모든 함수는 고차함수로 사용 가능

함수 타입 의미  예제 코드
() -> Unit 아무것도 안 받고, 아무것도 반환 안 함 { println("Hello") }
() -> String 아무것도 안 받고, String 반환 { "Hello" }
(String) -> Unit String 1개 받고, 반환 없음 { str -> println(str) }
(String) -> String String 1개 받고, String 반환 { str -> str.uppercase() }
(Int, Int) -> Unit Int 2개 받고, 반환 없음 { a, b -> println(a + b) }
(Int, Int) -> Int Int 2개 받고, Int 반환 { a, b -> a + b }
(String, Int) -> Boolean String, Int 받고 Boolean 반환 { name, age -> age > 18 }
// 함수 순서
// 1. main 함수가 a 함수를 b 함수에 파라미터로 넘김
// 2. b 함수는 받아온 a 함수에 값을 넘겨서 호출
// 3. 최종적으로 a 함수가 호출
fun main() {
    
    // 함수 b를 호출하되 함수 a 를 파라미터로 넘김
    // 고차함수로 넘기려면 함수 이름 앞에 ::(콜론) 두개를 붙여주면 됨
    b(::a)
    
    val c : (String)->Unit = { str -> println("$str 람다함수")}
    
    b(c)
    
}

fun a (str : String){
    println("$str 함수 a")
}

// 함수를 인스턴스로 받을 때 [(자료형)->반환형] 으로 만들 수 있음
fun b (function : (String)->Unit){
    function("b가 호출한")
}

 

 

  스코프 함수
함수형 언어의 특징을 좀 더 편하게 사용할 수 있도록 기본 제공하는 함수들

//  with - run과 동일한 기능, 단지 인스턴스를 참조연산자 대신 파라미터로 받는다는 차이 
//  also / let - apply / run과 같은 역할, 하지만 함수 내에 중복 변수가 선언되어있을 경우 값의 혼돈을 막기 위할 때 사용
// (파라미터로 인스턴스를 넘긴 것처럼 it 을 통해 인스턴스를 사용)
fun main() {
    
    var price = 5000
    
	// apply - 인스턴스를 생성한 후 변수에 담기전 초기화 과정을 수행할 때 사용
    var a = Book("우루쾅의 코틀린", 10000).apply{
        name = "[초특가] " + name
        discount()
    }
    
    // run - 이미 인스턴스가 만들어진 후 인스턴스의 함수나 속성을 scope 내에서 사용해야할 때 사용 
    a.run{
    	println("${name} 가격 ${price}")
    }
    
    a.let{
        println("${it.name} 가격 ${it.price}")
    }
}

class Book(var name:String, var price: Int){
    fun discount(){
        price -= 2000
    }
}

 

  object(싱글톤 객체)
object 로 생성된 객체는 최초 사용시 자동으로 생성되며 이후 코드 전체에서 공용으로 사용될 수 있음

fun main() {
    
    println(Counter.count)
    
    Counter.countUp()
    Counter.countUp()
    
    println(Counter.count)
    
    Counter.clear()
    
    println(Counter.count)
}

// 싱글톤 객체
// object 로 생성된 객체는 최초 사용시 자동으로 생성되며
// 이후 코드 전체에서 공용으로 사용될 수 있음
object Counter{
    var count = 0
    
    fun countUp(){
        count++
    }
    
    fun clear(){
        count = 0
    }
}

 

  companion (공유 객체)
서로 다른 인스턴스 임에도 companion object 를 공유하고 있기 때문에 모든 인스턴스에서 투표 수를 누적할 수 있음
클래스 내의 인스턴스를 사용하면서 공용으로 만드는 기능, 기존의 Static 클래스와 유사함

fun main() {
    
    var a = FoodPoll("짜장")
    var b = FoodPoll("짬뽕")
    
    a.vote()
    a.vote()
    
    b.vote()
    b.vote()
    b.vote()
    
    println("${a.name} : ${a.count} ")
    println("${b.name} : ${b.count} ")
    // 서로 다른 인스턴스 임에도 companion object 를 공유하고 있기 때문에
    // 모든 인스턴스에서 투표 수를 누적할 수 있음
    println("전체 갯수 : ${FoodPoll.total}")
}

class FoodPoll (val name:String){
    // 클래스 내의 인스턴스를 사용하면서 공용으로 만드는 기능
    // 기존의 Static 클래스와 유사함
    companion object {
        var total = 0
    }
    
    // 일반 사용할 함수는 companion 외부에 선언
    var count = 0
    
    fun vote(){
        total++
        count++
    }
}

 

observer 패턴
함수를 직접 선언하지는 않았지만 이벤트 발생시 즉각적으로 처리할 수 있도록 만드는 프로그래밍 패턴
이벤트 수신 + 이벤트 발생 및 전달

fun main() {
    // 1. start 함수 호출
    EventPrinter().start()
    
}

// observer 패턴
// 함수를 직접 선언하지는 않았지만 이벤트 발생시 
// 즉각적으로 처리할 수 있도록 만드는 프로그래밍 패턴
// 이벤트 수신 + 이벤트 발생 및 전달
interface EventListener{
    fun onEvent(count : Int)
}

class Counter(var listener : EventListener){
    fun count(){
        for(i in 1..100){
            // 3. 동작 진행 중 조건 맞을 시 onEvent 함수 호출
            if(i % 5 == 0) listener.onEvent(i)
        }
    }
}

class EventPrinter : EventListener{
    override fun onEvent(count : Int){
        print("${count} - ")
    }
    
    // 2. 함수에서 counter 멤버의 count() 호출
    fun start(){
        val counter = Counter(this)
        counter.count()
    }
}

 

 

  익명객체
아래코드에서는 Counter(익명객체) 로 사용
인터페이스를 구현한 객체를 코드 중간에서 즉시 생성하여 사용할 수 있음

fun main() {
    EventPrinter().start()
}

interface EventListener{
    fun onEvent(count : Int)
}

class Counter(var listener : EventListener){
    fun count(){
        for(i in 1..100){
            if(i % 5 == 0) listener.onEvent(i)
        }
    }
}

class EventPrinter {
    fun start() {
        // 익명객체
        // 아래코드에서는 Counter(익명객체) 로 사용
        // 인터페이스를 구현한 객체를 코드 중간에서 
        // 즉시 생성하여 사용할 수 있음
        val counter = Counter(object : EventListener {
            override fun onEvent(count : Int){
                print("${count} - ")
            }
        })
        counter.count()
    }
}

 

 

 리스트

- List<out T>
생성시에 넣은 객체를 대체, 추가, 삭제 할 수 없음
- MutableList<T>
생성시에 넣은 객체를 대체, 추가, 삭제가 가능함

fun main() {
    
    // List<out T>
    // 생성시에 넣은 객체를 대체, 추가, 삭제 할 수 없음
    val a = listOf("사과","딸기","배")
    println(a[1])
    
    for(fruit in a){
        println("${fruit} : ")
    }
    
    // MutableList<T>
    // 생성시에 넣은 객체를 대체, 추가, 삭제가 가능함
    val b = mutableListOf(6, 3, 1)
    println(b)
    
    b.add(4)
    println(b)
    
    b.add(2, 8)
    println(b)
    
    b.removeAt(1)
    println(b)
    
    b.shuffle()
    println(b)
    
    b.sort()
    println(b)
}

 

 

null 처리 방식

○ ?.
참조연산자를 실행하기 전에 객체가 null 인지 확인부터 하고 객체가 null이면 뒤의 연산자를 사용하지 않음
○ ?:
객체가 null 이 아니라면 그대로 사용하지만 null 이라면 연산자 우측의 객체로 대체됨
○ !!.
참조연산자를 사용할 때 null 여부를 컴파일 시 확인하지 않도록 하여 런타임시 NPE 발생하도록 방치하는 연산자

fun main() {
    
    var a: String? = null
    // ?.
    // 참조연산자를 실행하기 전에 객체가 null 인지 확인부터 하고 
    // 객체가 null이면 뒤의 연산자를 사용하지 않음    
    println(a?.uppercase())
    // ?:
    // 객체가 null 이 아니라면 그대로 사용하지만
    // null 이라면 연산자 우측의 객체로 대체됨
    println(a?:"default".uppercase())
    // !!.
    // 참조연산자를 사용할 때 null 여부를 컴파일 시 확인하지 않도록 하여
    // 런타임시 NPE 발생하도록 방치하는 연산자    
    println(a!!.uppercase())
}

 

 

 

출처

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

728x90
반응형
LIST