[Kotlin]스코프 함수-apply,also,run,let

dada·2021년 8월 27일
0

Kotlin

목록 보기
12/14
post-thumbnail

🟩스코프 함수?

  • 코틀린 표준 라이브러리는 객체의 컨텍스트 내에서 코드 블럭을 실행하기 위한 목적만을 가진 여러가지 함수를 제공. 이런 함수들을 람다식으로 호출할 때, 이는 임시로 범위(scope)를 형성함. 이 범위 내에서는 객체의 이름이 없어도 객체에 접근할 수 있으며 이러한 함수를 scope functions라고 함

  • 기본적으로, 이 함수들은 동일한 역할: 객체에 코드 블럭을 실행하는 것

  • 자신을 호출한 함수를 this , it으로 대체해서 사용할 수 있음

    • this사용:apply,run / it사용:also,let (it생략 불가)

🔷객체 반환 함수:apply,also

◾apply

  • 자신을 호출한 대상을 this.로 가르킴 클래스 내부의 함수를 사용하는 것과 동일한 효과이기에 this 생략 가능
  • 메인함수안에서 별도의 코드블록으로 인스턴스의 변수와 함수 조작하므로 코드가 깔끔해짐
  • 인스턴스 자신을 바로 반환해주며 객체 생성하자마자 조작한 다음에 객체 바로 변수에 넣기 가능
  • 인스턴스를 새로 만들고 특정 변수에 할당하기 전에 초기화 작업을 해주는 스코프
class Book(var name: String, var price: Int) {
    fun discount() {
        price - +2000
    }
}
fun main() {
 var a: String = "초특가" + Book("길동의 코틀린", 4000).name
 //이렇게도 가능한데 이렇게 하면 a는 String을 반환+코드드럽
 
 var apply: Book = Book("길동의 자바", 4000).apply {
        "초특가"+this.name
        this.discount()
 }
 
  var apply: Book = Book("길동의 자바", 4000).apply {
        "초특가"+name
        discount()
 }

◾also

  • apply랑 똑같은 기능이고 인스턴스 자체를 반환하는데 아래 2가지 차이가 있음
  • apply는 참조연산자(this) 없이 인스턴스의 변수와 함수를 사용할 수 있었는데 also는 같은 이름의 변수나 함수가 스코프 밖에 중복되어있는 경우에 혼란을 방지하려고 참조연산자(파라미터)it을 사용함
  • 이때의 it은 this와 다르게 생략불가
  • apply는 main최상단에 있는 price를 선언하면 인스턴스의 price가 아니라 main함수에서 만든 price가 호출됨 이는 인스턴스 내의 price속성보다 main에 속한 변수가 우선되기 때문임
fun main() {
    var price=5000
    var apply: Book = Book("자바", 4000).apply {
        println($price) //main함수에서 만든 price가 호출됨
    } 

    var also: Book = Book("자바", 4000).also {
          println($it.price) //인스턴스의 price호출
    }

🔶return값 반환 함수:run,let

◾run

  • apply처럼 run스코프 안에서 참조연산자(this)를 사용하지 않아도 된다는 공통점이 있지만 일반 람다함수처럼 인스턴스를 반환하는게 아니라 마지막 구문의 결과값을 return함
  • run스코프 안에서 return전에 print()한건 실행되네..
   val run = Book("자바", 4000).run {
        this.name = "자바스크립트"  //this써도되고 안써도 되고
        price = -2000
        name + price //마지막구문의 결과값을 return
    }

with
run 과 동일하나
a.run{ } 이 아니고 with{a} 요렇게 쓴다.
마지막 식의 결과를 리턴 한다
val s: String = with(StringBuilder("abc")) { append("def ").append("zzz") println("value: $this")toString() } println(s) //value: abcdefzzz //abcdefzzz

◾let

  • also랑 같은 역할
  • 인스턴스를 참조연산자 it으로 가르킴(it생략 불가)
     val let = Book("자바", 4000).let {
        it.name = "스크립트"
        it.price = -2000
        it.name + it.price //마지막구문의 결과값을 return
    }

🔺it으로 사용되는 스코프 함수 let / also특징

  • this로 사용되는 apply, run은 this생략 가능하지만 let과 also는 it생략 불가
  • it은 다른 이름으로 변경 가능함
  var also: Book = Book("다빈의 자바", 4000).also { target->
        target.name + "초특가"
        target.discount()
    }
  val let = Book("다빈의 자바", 4000).let { item->
        item.name = "지태의 자바스크립트"
        item.price = -2000
        item.name + item.price //마지막구문의 결과값을 return
    }

깔끔정리


     binding.apply {
     //apply로 묶으면서 객체 초기화할때 새로운 변수 선언도 당근 가능하구나
            val animation = AnimationUtils.loadAnimation(activity, R.anim.fade_in)
            val animation2 = AnimationUtils.loadAnimation(activity, R.anim.fade_out)
            ivSigninGithub.startAnimation(animation2)
            ivSigninGithub.startAnimation(animation)
            //binding.ivSigninGithub.startAnimation(animation)
        }

    with(binding) {
            recyclerMemo.adapter = memoAdapter
            recyclerMemo.layoutManager = LinearLayoutManager(this@RoomActivity)  
            //여기서의 this는 바인딩객체 가르켜서..
        }

        binding.run() {
            recyclerMemo.adapter = memoAdapter
            recyclerMemo.layoutManager = LinearLayoutManager(this@RoomActivity) 
        }

        binding.apply {
            recyclerMemo.adapter = memoAdapter  
            //마지막 결과값 리턴한거 변수에 담아서 쓰는게 아니니까 객체 초기화하는 스코프 함수 써도 될듯?
            binding.recyclerMemo.layoutManager = LinearLayoutManager(this@RoomActivity)  
        }
profile
'왜?'라는 물음을 해결하며 마지막 개념까지 공부합니다✍

1개의 댓글

comment-user-thumbnail
2021년 10월 2일

안녕하세요ㅎㅎ 저도 코틀린 공부중입니다!

답글 달기