Android

코틀린 유용한 기법

9tun 2025. 6. 9. 22:22

람다 함수

람다함수는 이름 없는 함수(익명 함수)입니다.
코틀린에서 함수를 변수처럼 전달하거나 짧게 정의할 때 사용합니다.

 

람다 함수 선언 및 호출

 

✅ 일반함수

fun 함수명(매개변수) { 함수 본문 }

fun sum(no1: Int, no2: Int): Int{
	return no1 + no2
}

 

 

✅ 람다함수

{ 매개 변수 -> 함수 본문 }

val sum = { no1: Int, no2: Int -> no1 + no2 }

 

람다 함수는 fun 키워드도 없고, 함수 이름도 없다.

 

🙋‍♂️ 람다 함수 사용 규칙에 대해서 좀 더 자세히 알려주세요.

👨‍🏫 네, 람다 함수 사용 규칙은 다음과 같습니다.

  • 람다 함수는 { }로 표현합니다.
  • { } 안에 "매개변수 -> 함수 본문"이 있습니다.
  • 함수 반환값은 함수 본문 마지막 표현식입니다.
  • 람다 함수는 이름이 없으므로 호출할 수 없습니다. 그래서 보통 변수에 대입해서 사용합니다.
val sum = { no1: Int, no2: Int -> no1 + no2 }
sum(10, 20)		// 람다 변수 sum 호출

 

매개변수 없는 람다 함수

매개변수가 없으면 걍 비워두면 됩니다.

{ -> println("function call")}	// 화살표 왼쪽 매개변수를 비워둔 람다 함수
{ println("function call")}		// 화살표까지 생략한 람다 함수

 

매개변수가 1개인 람다 함수

매개변수가 1개인 람다함수는 이렇게 사용하죠.

fun main(){
	val some = {no: Int -> println(no)}
    some(10)
}

 

이걸 (Int) -> Unit을 이용해서 아래와 같이 작성할 수도 있습니다.

fun main(){
	// Int를 받아, Unit을 반환한다. 
    // 여기서 Unit은 void로서 반환값이 없다는 뜻
    // it은 단일 매개변수를 나타내는 예약어
	val some: (Int) -> Unit = {println(it)}	
    some(10)
}

👨‍🏫 참고로, 단일 매개변수일 때는 매개변수 이름을 따로 짓지 않고 it 예약어를 사용할 수 있다.

단, it 매개변수는 변수 타입을 식별할 수 있을 때만 사용 가능합니다.

 

람다 함수 반환

람다 함수 반환값: 마지막 줄 실행 결과

fun main(){
	val some = { no1: Int, no2: Int ->
    println("in lambda function")
    no1 * no2	// 이게 반환값이 됩니다.
	}
    println("result: ${some(10, 20)}")
}

 

함수 타입과 고차 함수

Kotlin에서는 함수를 값처럼 변수에 저장할 수 있습니다.
이걸 위해서는 변수 타입을 함수 타입으로 선언해야 합니다.

 

함수 타입 선언

Int형 매개변수 2개를 받아서 결과를 Int로 반환하는 함수 선언은 다음과 같이 했었죠?

fun some(no1: Int, no2: Int):Int {
	return no1 + no2
}

 

이것을 아래와 같이 표현할 수 있습니다.

val some: (Int, Int) -> Int = { no1: Int, no2: Int -> no1 + no2 }

여기서 some은 함수 타입의 변수입니다.

 

타입 별칭: typealias

함수 타입을 별칭을 선언하는 키워드, typealias를 이용해 선언할 수 있습니다.

typealias MyFunType = (Int, Int) -> Boolean

fun main(){
	val someFun: MyFunType = {no1: Int, no2: Int -> no1 > no2}
    println(someFun(10, 20))
    println(someFun(20, 10))
}

false

true

 

👨‍🏫 Kotlin의 typealias는 c++의 typedef와 유사합니다.

 

매개변수 타입 생략

람다 함수를 정의할 때 만약 매개변수 타입을 유추할 수 있다면 타입 선언을 생략할 수 있습니다.

 

첫 번째 유형: typealias로 유추 가능

typealias MyFunType = (Int, Int) -> Boolean
val someFun: MyFunType = {no1, no2 -> no1 > no2}

MyFunType은 Int 타입 2개를 매개변수로 받아서 Boolean으로 반환하는 타입이니까 유추 가능하죠. 

 

두 번째 유형: 변수에 타입을 선언

val someFun: (Int, Int) -> Boolean = {no1, no2 -> no1 > no2}

 

세 번째 유형: 대입한 함수로 유추

val someFun = {no1: Int, no2: Int -> no1 > no2}

 

고차 함수

함수를 매개변수로 전달받거나 반환하는 함수

이렇게 사용할 수 있는 것은 함수를 값처럼 변수에 저장할 수 있기 때문입니다.

 

fun hofFun(arg: (Int) -> Boolean) : ()->String {
	val result = if(arg(10)){
    	"valid"
    } else{
    	"invalid"
    }
    return{"hofFun result: $result"}
}

fun main(){
	val result = hofFun({no -> no>0})
    println(result())
}

매개변수 arg의 타입이 Int형 변수를 받아서 Boolean을 반환하는 타입이군요. 

그리고 hofFun 함수 타입은 호출되면 String을 반환하네요. 

 

고차함수 실행 순서를 살펴봅시다.

  • arg = { no -> no > 0} 을 대입하며 함수 hofFun을 호출했습니다.
  • arg(10)은 10>0 이니까 true를 반환합니다.
  • result = "valid" 
  • () -> String으로 반환한 String: "hofFun result: $result"

고차 함수 hofFun 실행 결과

👨‍🏫 정리

hofFun은 함수 (Int) -> Boolean을 매개변수로 받고, 또 함수 () -> String을 반환하는 고차함수였습니다.

 

null 안정성

 

🙋‍♂️ null이 뭔가요?

👨‍🏫 null이란 객체가 주소를 가지지 못한 상태입니다.

null인 상태의 객체를 이용하면 널 포인트 예외가 발생합니다.

 

🙋‍♂️ null 안정성은 뭐예요?

널 포인트 예외가 발생하지 않도록 코드를 작성하는 것입니다.

 

코틀린이 제공하는 널 안정성 연산자를 이용한 코드

fun main(){
	var data: String? = null
    println("data length: ${data?.length ?:0}")
}
  • data?.length
    - ?를 Safe Call Operator 라고 합니다.
    - data가 null이 아니면 .length 호출
    - data가 null이면 null 반환

  • ?: 0
    - ?: 를 Elvis Operator라고 합니다.
    - 앞의 결과가 null이면 0 사용
    - Elvis 연산자는 기본값을 지정할 때 사용

null 안전성 연산자

 

null 허용: ?

var data1: String = "9tun"		// String은 not null 변수다.
data1 = null	// 오류 발생

var data2: String? = "9tun"		// String? 를 사용해서 nullable 변수로 선언
data2 = null	// 성공!

 

null 안전성 호출: ?.

nullable 변수에 null을 대입하면 null 포인트 예외가 발생할 수 있습니다. 따라서 변수가 null인 상황을 고려해야 합니다.

 

✅ nullable 변수의 잘못된 호출

var data: String? = "9tun"
var length = data.length	// nullable 변수 멤버에 이렇게 접근하면 오류가 납니다.

 

✅ nullable 변수 올바른 호출 

var data: String? = "9tun"
var length = data?.length	// ?. 을 사용해서 접근해야 한다.

 

👨‍🏫?. 연산자에 대해서

?. 연산자는 변수가 null이 아니면 멤버에 접근, null이면 멤버에 접근하지 않고 null 반환.

 

Elvis(엘비스): ?:

변수가 null일 때 대입하거나 실행해야 하는 구문이 있을 때 사용

fun main(){
	var data: String? = "9tun"
    println("data = $data: ${data?.length ?: -1}")
    data = null
    println("data = $data: ${data?.length ?:-1}")
}

data = 9tun: 4  
data = null: -1

 

예외 발생: !!

객체가 null일 때 예외를 일으키는 연산자

null 포인트 예외를 발생시켜야 하는 상황에서 사용

 

fun some(data: String?): Int {
	return data!!.length
}

fun main(){
	println(some("9tun")
    println(some(null))
}

 

'Android' 카테고리의 다른 글

뷰 배치 레이아웃  (0) 2025.07.02
뷰를 이용한 화면 구성  (0) 2025.06.13
코틀린 객체 지향 프로그래밍  (0) 2025.06.04
고틀린  (0) 2025.06.01
안드로이드 앱 기본 구조  (0) 2025.05.30