본문 바로가기
Language/Kotiln

[Kotlin] 코틀린 심화문법2 (확장함수/고차함수/표준라이브러리)

by 카프리썬 2022. 1. 31.
728x90

지금까지 코틀린 기본세팅을 진행했다.

2022.01.29 - [Kotlin] 코틀린 기본개념 - 코틀린이란? 도대체 왜 쓰는가? 특징!

2022.01.28 - [Kotlin] 코틀린 환경설정 - Intellj에서 코틀린 프로젝트 생성하기

2022.01.29 - [Kotiln] Intellj에서 코틀린 코딩컨벤션 Kotlin Style Guide 적용하기

2022.01.30 - [Kotiln] 코틀린 실행하기 - Scratch File (스크래치 파일) 만들기

 

그리고 간단한 기본문법도 살펴봤다. 

2022.01.29 - [Kotiln] 코틀린 기본문법1 (변수선언/함수선언/자료형/반복문/조건문)

2022.01.30 - [Kotiln] 코틀린 기본문법2 (NULL처리 : lateinit/lazy/!!/?/?.)

2022.01.30 - [Kotiln] 코틀린 기본문법3 (클래스와 컬렉션: List/Map/Set)

 

이번엔 조금 깊게 심화문법으로 몇가지를 더 살펴볼 예정이다. 

 

반응형

함수형프로그래밍

기본적으로 코틀린은 함수형 프로그래밍을 지원하기 때문에 모듈을 함수로 구현할수 있다.

그러다보니까 기본 라이브러리 함수들이 몇개 있다. 

 

확장함수 (extension functions)

기존에 정의된 클래스에 함수를 추가하는 기능이다. 

보통 자기가 만든 클래스에 함수를 추가하려면 [클래스명].[함수명]을 할 수 있지만,

기존에 정의된 클래스에 함수를 추가하기 위해선 확장함수를 정의해야한다. 

 

https://codechacha.com/ko/kotlin-extension-functions/

 

Kotlin - 확장 함수(Extension functions)에 대해서 알아보기

Extension functions는 기존에 정의된 클래스에 함수를 추가하는 기능입니다. 자신의 함수는 쉽게 추가가 가능하지만 다른 살마이 만든 라이브러리를 갖다 쓸때는 매우 어렵습니다. 코틀린은 이런 것

codechacha.com

 

고차함수 (higer-order functins)

함수의 인자로 함수를 넘기거나 함수를 리턴할 수 있는 기능이다.

val hello: () -> String = {"hello world"}

fun returnParamFunc(func: ()->String): () -> String {
    return func
}

fun main(args: Array<String>) {
    val returned = returnParamFunc(hello) //hello함수 인자 -> returnParamFunc 호출 
    print("${returned()}")
}

인자로 함수를 넘길때 함수의 타입을 명시해야한다.  예를 들어, func: ()->String 처럼 함수의 타입이 string.

->를 기준으로 왼쪽은 파라미터(인자), 오른쪽은 리턴값을 의미한다. 

리턴값이 없으면 Unit으로 표기 

 

 

Scope functions

자바에는 없지만 코틀린에서 제공하는 기본라이브러리 함수 중에 하나로 let,run.with,apply,also 함수가 있다. 

이들은 Scope functions 이라고 불리며 객체에 쉽게 접근할 수 있도록 해주는 함수이다.

덕분에 코드가 간결해지고 가독성이 높아진다. 

 

Scope functions 을 사용할때는 리시버람다함수를 넘겨준다. 

아래의 코드에서 person을 리시버라고 하고, let이후 {}를 람다함수라고 한다.

그래서 람다함수에서는 person객체에 접근할 수 있다. 

 

함수명 객체 접근방법 리턴형태  확장함수 가능여부
let it 람다식 결과 반환(block) 가능
also it 객체.also(it) (object) 가능
with this 인자로만 결과반환 불가능
run this 람다식 결과 반환(block) 가능 
run this 인자로도 쓰임  불가능
apply this 객체.apply(this) (object) 가능

 

let() 함수

it으로 리시버에 접근하고, 람다함수의 마지막결과를 리턴한다. 

블록에 자기자신을 인수로 전달하고 수행된 결과를 반환한다. 인수로 전달되는 자기자신은 it으로 참조한다. 

let()함수는 아래처럼 한번에 여러함수를 호출할때 사용한다. 

val numbers = mutableListOf("one", "two", "three", "four", "five")
numbers.map { it.length }.filter { it > 3 }.let {
    println(it)
    // it의미 : numbers 리스트 아이템들의 length
    // 즉, it이 3이상인 것들만 it(length)출력
    //출력 : [5,4,4]
}

또는 ?키워드랑 같이 쓰이면서 NULL이 아닐때만 리시버가 동작하도록 할때 사용한다. 

val str: String? = "Hello"   
val length = str?.let {
    println("let() called on $it")        
    it.length
}

// 실행 결과 : 5
println("result: $length")

 

also() 함수

it으로 리시버에 접근하고, 람다함수의 마지막결과를 리턴한다. 

let()과 기능은 비슷하지만, apply처럼 객체의 상태를 변화시키고 그 객체를 다시 반환할때 사용한다.

리시버 스스로를 리턴하기 때문에 연속적으로 객체를 호출할수 있다. 

val numbers = mutableListOf("one", "two", "three")
numbers
    .also { println("The list elements before adding new one: $it") }
    .add("four")

let()과 also()가 동시에 사용하게 될 경우 아래처럼 쓰일수 있다. 

let()은 식의 결과를 반환하고, 그 결과를 다시 also()에게 넘겨서 상태를 변화시킨다. 

fun makedir(path:String):File {
  val result = File(path)
  result.mkdidrs()
  return result
 }
 
 fun makeDir(path:String)=path.let{File(it)}.also(it.mkdirs()}

 

728x90

With() 함수

this로 리시버에 접근하고, 람다함수의 마지막 결과를 리턴한다.

인수로 전달되는 자기자신을 this로 참조한다. 이렇게 this 키워드를 생략할 수도 있고, 리턴값 생략을 권장한다.

let은 리시버의 확장함수로 쓰이지만 with은 그렇지 않다. 그래 리시버객체는 with(리시버객체){람다함수}로 인자로만 전달할 수 있다. 

val numbers = mutableListOf("one", "two", "three")
val firstAndLast = with(numbers) {
    "The first element is ${first()}," +
        " the last element is ${last()}"
}
println(firstAndLast)

 

Run() 함수

with과 마찬가지로 this로 리시버에 접근하고, 람다함수의 마지막 결과를 리턴한다.

하지만 with과 다르게 확장함수로 쓸 수 있다. 그래서 리시버객체를 리시버객체.run{람다함수}처럼 함수처럼 쓸 수 있다. 

run()함수는 람다함수에서 여러값을 초기화하고, 리턴값을 어떤 객체의 초기값으로 사용한다.

//객체에서 호출하는 방식으로 사용가능
val service = MultiportService("https://example.kotlinlang.org", 80)

val result = service.run {
    port = 8080
    query(prepareRequest() + " to port $port")
}

위와 같은 내용을 let()함수로 똑같이 쓸 수도 있는데 차이점이라면 run()함수는 굳이 확장함수로 사용하지 않을때도 사용할수 있다. 

그래서 Run()함수는 익명함수처럼 사용하거나 객체에서 호출하는 방법 모두 제공한다. 

//익명함수처럼 사용가능
val hexNumberRegex = run {
    val digits = "0-9"
    val hexDigits = "A-Fa-f"
    val sign = "+-"

    Regex("[$sign]?[$digits$hexDigits]+")
}

for (match in hexNumberRegex.findAll("+1234 -FFFF not-a-number")) {
    println(match.value)
}

 

apply()함수

with,run과 마찬가지로 this로 리시버에 접근하고, 람다함수의 마지막 결과를 리턴한다.

객체의 상태를 변화시키고 그 객체를 다시 반환할때 사용한다.

val adam = Person("Adam").apply {
    age = 32
    city = "London"        
}
//person객체의 age,city과 변경된채 리턴된다.

 

참고

https://codechacha.com/ko/kotlin-standard-library-functions/

 

Kotlin의 Scope functions(let, run, with, apply, also)에 대해서 알아보기

Scope functions는 let, run, with, apply, also를 말합니다. Scope functions는 객체에 접근하는 방법을 쉽게 해 줍니다. 이런 함수들을 이용하면 코드가 간결해지고, 가독성을 높여줄 수 있습니다. 위의 5개 함

codechacha.com

https://velog.io/@gosgjung/3%EB%B6%84-kotlin-8-%EC%BD%94%ED%8B%80%EB%A6%B0-%ED%95%A8%EC%88%98%ED%98%95-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EB%B0%8F-%EA%B8%B0%ED%83%80-%EA%B8%B0%EB%8A%A5

 

3분 kotlin (8) - 코틀린 함수형 프로그래밍 및 기타 기능

코틀린 기본 라이브러리는 유용한 함수들을 제공한다. 이에 대해 알아보자.확장함수원래 있던 클래스에 기능을 추가하는 함수형변환숫자형 자료형끼리 쉽게 형변환 가능형 체크변수의 형이 무

velog.io

https://junyoung-developer.tistory.com/134?category=930228 

 

[Kotlin] 클로저와 표준 함수 let, also, apply, run, with

모든 내용은 이지스퍼블리싱의 Do it! 코틀린 프로그래밍을 바탕으로 정리한 것입니다. Kotlin의 표준 함수 Kotlin 표준 라이브러리에서 제공하는 함수를 이용하면 코드를 더 단순화하고 가독성을

junyoung-developer.tistory.com

https://sabarada.tistory.com/172?category=941106 

 

[kotlin] 코틀린 차곡차곡 - 8. Scope Function

안녕하세요. 오늘은 코틀린 Scope Function에 대해서 알아보도록 하겠습니다. Scope Function 란 코틀린으 표준 라이브러리에서는 Scope Function을 지원하고 있습니다. Scope Fuction은 객체 컨텍스트 내에서

sabarada.tistory.com

 

반응형