티스토리 뷰

728x90

먼저! 위에 5가지 사항을 범위 지정 함수 라고 한다. 

일단, 크게 3가지로 나눠서 보면 된다. 

 with  ,   apply <-> also  ,  let <-> run 
(apply, also 는 거의 비슷, let과 run도 거의 비슷하니 서로 비교하면 이해하기 쉽다)

1. with

객체를 만들고 반환. 그 이후에 그 객체의 중복 사용이 있는 경우

- before

Class Person {
    var name: String? = null
    var age: Int? = null
}

val person: Person = Person()
print(person.name)
print(person.age)

 

- after

val person: Person = Person()
with(person) {
    print(name)
    print(age)
}

 


2. also

객체를 만들고 반환을 하기 전에 사용할 함수
- 함수 내용에서 객체의 속성값은 건드리지 않는다. 
- 유효성 검사에 유용하다. (속성값은 건드리지 않으니)

<예시 1>

val person: Person = Person().also {
   print(it.name)
   print(it.age)
}

 

<예시 2> - 유효성 검사

- before

class Book(author: Person) {
   init {
      requireNotNull(author.age)
      print(author.name)
   }
}

 

- after

class Book(author: Person) {
   val author = author.also {
      requireNotNull(it.age)
      print(it.name)
   }
}

 


3. apply

객체를 만들고 반환을 하기 전에 사용할 함수
- 함수 내용에서 객체의 속성값만 건드린다.
- 객체 초기화에 사용

- before

val peter = Person()
peter.name = "Clark"
peter.age = 18

 

- after

val peter = Person().apply {
    name = "Peter"
    age = 18
}    

 


4. let 

유효한 값일 경우 실행
(주로 Null이 아닌경우 실행하도록 하는 safe call 메서드)

block 안에 it 이 생략되어 있다.

 


5. run

let 과 같다. 

block 안에 this 가 생략되어 있다. 

 

let 과 run은 따로 예제를 적지 않습니다. (별로 안햇갈려서..)

 


범위 지정 함수를 골고루 잘 사용한 예제

private fun insert(user: User) = SqlBuilder().apply {
   append("INSERT INTO user (email, name, age) VALUES")
   append("(?", user.email)
   append(",?", user.name)
   append(",?)", user.age)
}.also {
    print("Executing SQL update: $it.")
.run {
    jdbc.update(this) > 0
}

 


아래 범위 지정 함수의 정의를 살펴보면 각각의 함수들의 왜 위에처럼 동작하는지 이해할 수 있다. 

inline fun <T, R> with(receiver: T, block: T.() -> R): R {
    return receiver.block()
}
inline fun <T> T.also(block: (T) -> Unit): T {
    block(this)
    return this
}
inline fun <T> T.apply(block: T.() -> Unit): T {
    block()
    return this
}
inline fun <T, R> T.let(block: (T) -> R): R {
    return block(this)
}
inline fun <T, R> T.run(block: T.() -> R): R {
    return block()
}

 


또 뭐가 있을까?

1. takeIf

  • add v1.1
  • Returns this value if it satisfies the given [predicate] or null, if it doesn't
    (조건이 맞으면 객체 반환, 아니면 null 반환)
data class Block(var name: String = "", var age: Int = 10)

fun test() {
   val block = Block("ABC")
   println("out ${block.takeIf { it.age > 10 }}")
}  


// 출력 결과: out null

 

2. takeUnless

  • add v1.1
  • Returns this value if it does not satisfy the given [predicate] or null, if it does
    (조건이 맞으면 null, 아니면 객체 반환)
  • takeIf의 반대

 

[참고 출처]
https://takhyeongmin.github.io/2018/12/03/kotlinUsefulFunction2/

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함