-
Scope Functions (let, with, also, apply, fun)Android 2024. 3. 16. 09:06
어떤 객체의 변수, 메소드 등을 불러올때는 scope function 을 쓰는게 편리할 때가 있다.
Scope 내 접근방식 this Scope 내 접근 방식 it 블록 수행 결과 반환 run, with let 객체 자신 반환 apply also 수신 객체 자체를 람다로 전달 수신객체를 람다의 파라미터로 전달 뒤에 코드에 주석처리한 부분을 보면 이해가 되는데, T는 수신객체를 의미한다. 이때, 수신객체는 it으로 사용할 수 있는데 따라서 scope 내 접근 방식이 it 인 경우, 수신객체를 람다의 파라미터로 전달한다는 뜻이다. block 내부(중괄호)는 람다함수의 소스코드를 의미한다.
1. let 함수
중괄호 블록 안으로 객체를 it 으로 전달하고, 블록 수행 결과를 반환한다. 이때, strNum 의 자료형은 let 함수를 쓴다고 변하지 않는다. strNum 의 자료형은 Int형이 아니라 여전히 String형이다.
fun main() { var strNum = "10" var result = strNum?.let { it.toInt() } println("result : ${result}") // Int 형 println("strNum : ${strNum}") // String 형 } // 수신객체(T)를 람다의 파라미터로 전달 // public inline fun <T,R> T.let(block:(T) → R): R
2. with 함수
중괄호 블록 안으로 객체를 this 로 전달하고, 블록 수행 결과를 반환한다. 이때 scope 내에서 this 를 생략해서 편리하게 쓸 수 있다. 여전히, alphabet 은 변하지 않는다. this 를 생략해서 쓸 수 있다는 점에서 받아오는 객체는 반드시 null 이 아닐때 사용해야 한다. 참고로 subSequence(a,b) 함수는 해당 문자열의 index a 부터 index b-1 까지의 문자를 반환한다.
fun main() { var alphabet = "abcd" with(alphabet) { var result = this.subSequence(0,3) // subSequence(0,3) 는 index : 0 ~ index : 2 까지 출력한다는 의미이다. var result2 = subSequence(0,2) // this 는 생략가능 println("result : ${result}") // result : abc println("result2 : ${result2}") // result2 : ab } } // 수신객체 자체(T.()) 를 람다로 전달 // public inline fun <T,R> with(receiver: T, block:T.() → R) : R
3. also 함수
중괄호 블록 내로 객체를 it 으로 전달하고, 결과값으로 객체를 반환한다. apply 함수와 함께 자주 사용한다.
이때, also 함수를 사용하면 객체 자체의 정보도 변경된다.
fun main() { var student = Student("참새",3) var student2 = student.also { it.age=7 // student 자체의 age 변수값도 7로 바뀜 } student.displayInfo() // 이름: 참새, 나이: 7 student2.displayInfo() // 이름: 참새, 나이: 7 } class Student(name:String, age:Int) { // 주생성자 사용 var name : String var age : Int init { this.name=name this.age=age } fun displayInfo() { println("이름: ${name}, 나이: ${age}") } } // 수신객체(T) 를 람다의 파라미터로 전달 // public inline fun <T> T.also(block: (T) → Unit) : T
4. apply 함수
apply 함수 같은 경우 객체를 중괄호 안에서 this 로 전달하는데, this 는 생략해서 사용 가능하다. 이때, apply 함수 앞에 붙는 객체도 내용이 변경된다.
fun main() { var student = Student("참새",3) var student2 = student.apply { // this.age=10 name="비둘기" //이때, 매개변수로 받는 this는 생략가능하다. apply 함수의 객체인 student 도 값이 변경된다. } student.displayInfo() // 이름: 비둘기, 나이: 3 student2.displayInfo() // 이름: 비둘기, 나이: 3 } // 수신객체 자체(T.())를 람다로 전달 // public inline fun <T> T.apply(block: T.() → Unit): T
글쓴이 물음표
- this 랑 it 으로 왜 구분해서 객체를 전달받는거지?
5. run 함수
객체를 호출하지 않고 run 함수를 이용하여 작성할 수 있다.
fun main() { var totalPrice = run { val computer = 10000 val mouse = 5000 computer + mouse } println("totalPrice : ${totalPrice}") // totalPrice : 15000 }
run 함수 내에서 this 는 생략가능한데, with 와 달리 null 체크를 수행할 수 있어 with 보다 더욱 안전하게 사용가능하다.
fun main() { var student = Student("참새",5) student.run { displayInfo() // 이름: 참새, 나이: 5 } } // 수신객체 자체(T.())를 람다로 전달 // public inline fun <T,R> T.run(block: T.() → R) : R
scope function을 중첩으로 사용할 때, 모든 수식객체를 it 으로 사용하면 문제가 발생할 수 있다. 이때는 람다식 내부를 it 대신 다른 문자를 사용하여야 한다.
fun main() { Person().also { it.name="비둘기" it.age=3 // val sparrow = Person().also { // it.name="참새" // 누구의 it인지 모른다 // it.age=10 // } val sparrow = Person().also { c -> c.name="참새" c.age=10 } it.child=sparrow } } data class Person( var name: String = "", var age: Int? = null, var child: Person? = null )
'Android' 카테고리의 다른 글
MVC, MVP, MVVM, MVI (0) 2024.03.19 확장함수 (0) 2024.03.18 Pair,Triple 클래스 (0) 2024.03.15 자료형변환, 업캐스팅, 다운캐스팅, Is 키워드 (0) 2024.03.15 여러 복합 계산 : 후위연산자, Stack 개념 활용 (0) 2024.03.14