본문 바로가기
안드로이드 프로그래밍/문법정리

[kotlin] 코틀린 스코프 함수 let, with, run, apply, also 차이 비교 정리

by 1chanhue1 2023. 8. 10.

패스트 캠퍼스, 35개 프로젝트로 배우는 Android 앱 개발 feat. Jetpack Compose 초격차 패키지 Online 강의안

 

 

1. let 

    1. 수신객체를 받기 위해서 it 을 사용(생략 불가능),

        명시적으로 local variales 선언 가능

    2. 마지막 줄이 return 값 ( 람다식과 동일한 것을 볼 수 있음)

    3.  let을 많이 쓰는경우 ?  non-null 체크 

 

사용 예시

class User(
    val name: String,
    var age: Int,
    val gender: Boolean,
    var hasGlasses: Boolean
)
val user: User? = User("나", 10, true,true)
val age = user?.let {
    it.age //it으로 받음 , 마지막 줄 it.age가 리턴됨
}
val age1 = user?.let {
    user->user.age // 명치적으로 local variable 선언 가능 ,
}
val age2=user?.let{
    it.age=3
    it.age
}

println(age) // 10 출력
println(age1) // 10 출력
println(age2) // 3 출력
println(user?.age) // 3출력

 non-null 체크 시 유용하다. 

val str: String? = "hello world"
if (str != null) { println(str) } // 기존 방식
str?.let { println(str) } // let을 사용한 경우 

2. run

  1. 수신객체를 받기 위해서 this를 사용(생략가능),

      명시적으로 local variales 선언 불가능

  2. 마지막 줄이 return 값 ( 람다식과 동일한 것을 볼 수 있음)

  3.객체를 초기화하고 retun 값이 있을 경우 

 

val kid=User("아이",4,false,true)

val kidAge=kid.run{
    age // 값을 접근 할 때 그냥 접근 가능(this 생략)
}
val kidAge1=kid.run{
    this.age=5
    this.age
}
println(kidAge) // 4출력
println(kidAge1) // 5출력

3.  Apply

    1. 수신객체를 받기 위해서 this를 사용(생략가능),

        명시적으로 local variales 선언 불가능

    2.  return 값이 수신객체

    3. 객체 초기화 할 경우 

 

 

run과 apply 차이 비교 

val kid=User("아이",4,false,true)

val kidName=kid.run{
    name //run 사용 , 마지막줄 return
}
println("name 리턴: "+ kidName) //출력 아이

val kidName1=kid.apply{
    name // apply 사용, 객체 리턴 
}
println("객체 리턴: "+ kidName1) //출력 org.techtown.part0.kotlin.part2.User@2812cbfa
val female =User("철수",20,true,true)

val femaleValue=female.apply{

    hasGlasses=false // var라서 변경가능

    // 어떤 코드를 쳐도 수신객체가 반환 될 것임

}
println(femaleValue.hasGlasses) // false 출력
println(female.hasGlasses)  // false 출력

 특정 객체를 생성하면서 함께 호출해야 하는 초기화 코드가 있는 경우 사용

// apply()함수를 사용하지 않고 초기화를 하는 경우
val param = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT)
param.gravity = Gravity.CENTER_HORIZONTAL
param.weight = 1f
param.topMargin = 100
param.bottomMargin = 100
//  apply() 함수를 사용하게 되면
val param = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
    gravity = Gravity.CENTER_HORIZONTAL
    weight = 1f
    topMargin = 100
    bottomMargin = 100
}

4.  Also

  1. 수신객체를 받기 위해서 it를 사용(생략 불가능),

      명시적으로 local variales 선언 가능
  2. return 값이 수신객체
  3. 로그 찍을 때 많이 사용됨

 

val maleValue=male.also{
    it.name
    it.hasGlasses=false
    // 어떤 난리를 쳐도 수신객체가 반환 될 것임

}
println(maleValue.hasGlasses)  // false 출력

객체의 속성을 전혀 사용하지 않거나 변경하지 않고 사용하는 경우에 also를 사용한다.
객체의 데이터 유효성을 확인하거나, 디버그, 로깅 등의 부가적인 목적으로 사용할 때에 적합하다.

val numbers = mutableListOf("1", "2", "3")
numbers
    .also { println("The list elements before adding new one: $it") }
    .add("4")

 

5. With

     1. 수신객체를 받기 위해서 this를 사용(생략 가능),

        명시적으로 local variales 선언 불가능
     2. 마지막 줄 리턴됨
     3. 확장함수는 아니다.

val male=User("민수",17,false,true)

val result=with(male){
    hasGlasses=false
    true
}

println(result) //true 출력 

with() 함수는 인자로 받는 객체를 이어지는 블록의 리시버로 전달하며, 블록의 결과값을 반환한다.

run() 함수와 기능은 동일하나, 리시버로 전달할 객체가 어디에 위치하는지가 다름

with(recyclerView) {
    layoutManager = LinearLayoutManager(this)
    adpater = viewAdapter
}