본문 바로가기

Kotlin

(Kotlin) 어렵지만 쓰다보면 편한 Scope 함수에 대해 알아보자

  • 코틀린에는 scope 함수라는 기능이 있다

 

그렇지만 이 scope 함수가 많지만 비슷하게 보이는 경우가 많아서 헷갈리는 경우가 많다

 

오늘은 그래서 scope 함수에 대해서 정리를 해보려고 한다

 

Scope 함수를 이해가 위해서는 먼저 고차함수와 람다 표현식를 이해하는 것이 좋다

 

  • 고차함수
    • 함수를 인자로 받거나 결과 값으로 함수를 반환 할 수 있는 함수
    • 고차함수는 function1(100, 100) -> {} 같은 람다 함수 방식으로 표시 할 수 있다
    • 또한 :: (함수 참조 연산자(?))를 사용하여 함수를 표현할 수 있다 -> 해당 내용은 다른 포스팅에서 자세하게 다뤄볼 예정입니다
fun addTwoNumbers(number1: Int, number2: Int): Int {
	return number1 + number2
}

fun addTenNine(function: (Int, Int) -> Int) {
    val result: Int = function(10, 9)
    println("결과는 $result 입니다")
}


addTenNine(::addTwoNumbers)

 

  • 람다 표현식
    • 항상 중괄호로 묶여서 사용된다
    • 매개 변수 선언은 중괄호 안에 들어가며 선택적으로 사용이 가능하다
    • 함수의 몸은 -> 다음에 표현한다
// 전체 구문은 이런 방식으로 표현이 된다
val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }

// 매개변수의 타입이 명시되있을 경우 람다 표현식 안에 타입을 지정해주지 않아도 된다

val sum: (Int, Int) -> Int = { x, y -> x + y }

// 람다식만 사용할 경우 반드시 타입을 명시해줘야 한다

val sum = { x: Int, y: Int -> x + y }
  • Scope 함수
  • 객체 블록에 내에서 코드 블록을 실행하는 것이 유일한 목적일 경우 사용이 가능하다
  • 객체에서 바로 코드 블록을 실행 할 수 있다는 특징이 있다
  • 스코프 함수의 예시
//Person이란 클래스를 해당 값을 받아서 생성할 경우 let을 통해서 바로 실행이 가능하다
Person("Alice", 20, "Amsterdam").let {
    println(it)
    it.moveTo("London")
    it.incrementAge()
    println(it)
}

 

  • Scope 함수의 종류
기능 참조 객체 반환 값 확장 가능 여부
let it 람다의 결과를 반환 가능
run this 람다의 결과를 반환 가능
run   람다의 결과를 반환 Context 객체 없이 호출이 된다
with this 람다의 결과를 반환 Context 객체를 인수로 사용한다
apply this Context 객체를 반환 가능
also it Context 객체를 반환 가능

 

  • let
    • 타입 T에 대한 확장 함수  -> T에 관한 내용은 다른 포스팅에서 자세하게 다뤄볼 예정입니다
    • null이 아닌 객체에 대해서 람다 식으로 실행한다
      • ?.(세이프콜)을 활용하여 null인 경우를 처리가 가능하다 -> ?.에 관한 내용은 다른 포스팅에서 자세하게 다뤄볼 예정입니다
    • Local 범위의 변수로 표현식을 도입한다
    • 람다식 내부의 마지막 줄에 식이 아닌 변수나 객체 단일로 존재할 시, 그 값이 곧 반환값이 된다
getPerson()?.let {
    // null 이 아닐때만 실행이 된다
    println(it)
}

// 아래의 코드는 let 함수를 쓰지 않고 만든 코드
val person: Person? = getPerson()
if (person != null) {
  println(person)
}
  •  apply
    • 값을 수신자로 정해서 지정된 기능 블록을 호출하고 값을 반환하는 함수
    • 수신 객체의 함수를 따로 사용하지 않고 수신 객체 자신을 다시 반환하려고 할 경우에 사용한다
    • 주로 객체를 초기화 하는 경우에 많이 사용한다
val kim = Person().apply{
	name = "Kim"
    age = 20
}


//apply 함수를 쓰지 않은 경우
val lee = Person()
lee.name = "lee"
lee.age = 21
  • run
    • 지정된 블록을 호출하고 결과를 반환하거나 값을 수신자로 해서 지정된 기능 블록을 호출하고 그 결과 값을 반환 한다
    • 어떠한 값을 계산하거나 여러개의 지역변수의 범위를 제한 할 필요가 있는 경우 사용한다
    • 매개변수로 전달된 명시적 수신 객체를 암시적 수신 객체로 변환 할 때 사용한다
    • 객체의 구성 및 결과 계산을 할 경우 사용된다
  • also
    • T의 확장 함수로서 수신 객체가 암시적으로 제공이 된다
    • 수신 객체 지정 람다식에 매개변수 T로 코드 블록 내에 명시적으로 전달된다
    • 코드 블록 내에서 전달된 수신 객체를 그대로 다시 반환
    • 수신 객체 람다식 내부에서 수신 객체의 함수를 사용하지 않고 수신 객체 자신을 반환하려고 하는 경우에 사용한다
    • 주로 추가적인 효과를 구현할 때 사용된다
  • with
    • 수신 객체가 매개 변수 T로 제공이 된다
    • 수신 객체가 지정 람다식이 T의 확장 함수 형태로 코드 블록 내에 수신 객체가 암시적으로 전달된다
    • 람다식을 실행한 결과를 반환한다
    • Null이 될 수 없는 수신 객체이고 결과가 필요하지 않은 경우에만 사용한다
val person: Person = getPerson()

getPerson.let{
	it.name = "Kim"
    it.age = 12
}

with(person){
	print(name)
    print(age)
}

 

 

  • run과 also는 코드 바로 업데이트 드리겠습니다 감사합니다