728x90

java 를 주 언어로 사용하시다가 kotlin 으로 넘어오는 경우가 많은데 kotlin 을 처음 접하게 되면 드는 생각이 OOP를 지원하지만

생각보다 많은것들이 함수형으로 코드를 작성하는것이 더 편하다는 생각이 든다.

 

오늘은 그중에서도 With 과 Apply function 에 대해서 알아보자.

 

With

어떤 객체의 이름을 반복하지 않고도 그 객체에 대해 다양한 연산을 수행할 수 있다면 좋을 것이다.

다양한 언어가 그런 기능을 제공한다.

코틀린도 마찬가지 기능을 제공하지 만 언어 구성 요소로 제공하지 않고 With라는 라이브러리 함수를 통해 제공한다.

fun main() {
    println(alphabet())
}

fun alphabet() = with(StringBuilder()) {
    for (letter in 'A'..'Z') {
        append(letter)
    }
    append("\nNow I Know the alphabet!")
    toString()
}

 

기존에 자바코드로 작성 했다면

Stringbuilder sb = new Stringbuiler();
sb...
....

처럼 sb 라는 변수 이름이 반복되었을 것이다.

 

with 을 처음보면 언어가 제공해주는 마법같이 보일 수도 있지만 kotlin 언어 특성상 with은 2개의 파라미터를 받고있는 함수다.

첫번째 파라미터는 Stringbuiler 를 받고 있고 두번째는 람다를 받는다.

 

kotlin 에서는 람다를 괄호 밖으로 빼내는 관례를 사용한다.

 

Apply

/**
 * apply 함수는 거의 with 과 동일하다.
 * 유일한 차이는 apply는 항상 자신에게 전달된 객체 (수신 객체) 를 반환한다는 점뿐이다.
 */
fun alphabetVerApply() = StringBuilder().apply {
    for (letter in 'A'..'Z') {
        append(letter)
    }
    append("\nNow I Know the alphabet!")
}.toString()

apply 는 확장함수로 정의돼 있다. apply의 수신객체가 전달받은 람다의 수신객체가 된다.

 

apply를 실행한 결과는 Stringbuiler 객체다. 따라서 그 객체에 대한 method 는 모두 실행 할수 있다 toString 도 마찬가지

 

응용하기

data class Person(
    var name: String,
    var age: Int
)

fun createPerson(name: String, age: Int) = Person(name, age).apply {
    this.name = "${name}님"
    this.age = age + 1
}

person 이라는 인스턴스를 만드는 createPerson 함수이다. apply 람다 내부에서는 this 로 현재 인스턴스의 필드 값에 접근 할수 있다.

마찬가지로 이 함수의 return 은 새로만든 Person class 의 인스턴스이다.

728x90