2024. 3. 11. 13:03, ๐ฑAndroid Study
๋ฐ์ํ
10 ์ค์ฝํ ํจ์ (Scope Functions)
- ์ฝ๋๋ฅผ ์ถ์ฝํด์ ํํํ ์ ์๋๋ก ๋์์ฃผ๋ ํจ์, ์์ญ ํจ์
- ์ฌ์ฉ๋ฒ์ ํจ์์ฒ๋ผ ์ฐ์ง ์๊ณ run, let์ฒ๋ผ ๊ดํธ ์์ด ์ผ์ข ์ ํค์๋ ๊ฐ์ด ์ฌ์ฉ
- lateinit๊ณผ ํจ๊ป Safe Call ๋จ์ฉ์ ๋ง์์ฃผ๋ ์ญํ , ๋ง์ด ์ฌ์ฉ
- ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ ๋ ์์๋ก Scope๋ฅผ ๋ง๋ค์ด์ ํธ๋ฆฌํ ์ฝ๋ ์์ฑ์ ๋์์ค
- ์ค์ฝํ ๋ด์์๋ ๊ฐ์ฒด์ ์ด๋ฆ์ ํตํด ์ผ์ผํ ์ฐธ์กฐํ ํ์ ์์ด ๊ฐ์ฒด๋ฅผ ์ ๊ทผํ๊ณ ํธ๋ค๋งํ๋ ํธ๋ฆฌํจ
- ์ข ๋ฅ: run, let, apply, also, with
์ค์ฝํ ํจ์ ์ข ๋ฅ
- ์์ ์ ํจ์ ์ค์ฝํ(์ฝ๋ ๋ธ๋ก) ์์์ ํธ์ถํ ๋์์ this ํน์ it๋ก ๋์ฒดํด์ ์ฌ์ฉํ ์ ์์
let
var list = mutableListOf("Scope", "Function")
list.let { // it -> ์๋ต๋ ํํ. it -> ๋์ ์ target -> ๋ฑ์ผ๋ก ๋ณ๊ฒฝ ๊ฐ๋ฅ
val listSize = it.size // ๋ชจ๋ ์์ฑ๊ณผ ํจ์๋ฅผ it.๋ฉค๋ฒ๋ก ์ฌ์ฉํ ์ ์์
println("๋ฆฌ์คํธ์ ๊ธธ์ด let = $listSize")
}
// MutableList์ size ์์ฑ์ let ์ค์ฝํ ์์์ it.size๋ก ํธ์ถ
var strNum = "10"
var result = strNum?.let { // ์ค๊ดํธ ์์์๋ it์ผ๋ก ํ์ฉํจ
Integer.parseInt(it) // ์ฌ๊ธฐ์์ it์ strNum
}
println(result!!+1)
- ํจ์ ์์ญ ์์์ ํธ์ถํ ๋์์ it์ผ๋ก ์ฌ์ฉ
- it์ ์๋ต ๋ถ๊ฐ. ๋ค๋ง target ๋ฑ ๋ค๋ฅธ ์ด๋ฆ์ผ๋ก ๋ฐ๊ฟ ์ ์์
with
var alphabets = "abcd"
with(alphabets) {
var result = subSequence(0,2) // this.subSequence(0,2)์ง๋ง this. ์๋ต
println(result)
}
- ์ค๊ดํธ ๋ธ๋ก์์ this๋ก ์์ ์ ๊ฐ์ฒด๋ฅผ ์ ๋ฌํ๊ณ ์ฝ๋๋ฅผ ์ํ
- this๋ ์๋ตํด์ ์ฌ์ฉํ ์ ์์ผ๋ฏ๋ก, ๋ฐ๋์ null์ด ์๋๋๋ง ์ฌ์ฉํ๋๊ฒ ์ข์ (run๊ณผ ๋ฌ๋ฆฌ null์ฒดํฌ ๋ถ๊ฐ)
run
var list = mutableListOf("Scope", "Function")
list.run {
val listSize = size
println("list์ ๊ธธ์ด run = $listSize")
}
//MutableList๋ฅผ run ํจ์๋ฅผ ์ฌ์ฉํด์ ์ค์ฝํ๋ฅผ ์ง์ ํ ํ, ๋ด๋ถ์์ size ํ๋กํผํฐ๋ฅผ ์ง์ ํธ์ถ
// ๊ฐ์ฒด์์ ํธ์ถํ์ง ์๋ ๊ฒฝ์ฐ
var totalPrice = run {
var computer = 10000
var mouse = 5000
computer+mouse
}
println("์ด ๊ฐ๊ฒฉ์ ${totalPrice}์
๋๋ค")
//๊ฐ์ฒด์์ ํธ์ถํ๋ ๊ฒฝ์ฐ
fun main() {
var student = Student("์ฐธ์", 10)
student?.run { // ๋๊ฐ์ด this๋ฅผ ์๋ตํ ์ ์๋ with๊ณผ ๋ฌ๋ฆฌ null์ฒดํฌ ๊ฐ๋ฅ
displayInfo() // student.displayInfo() ์ง๋ง this.์ ์๋ตํจ
}
}
class Student(name: String, age: Int) {
var name: String
var age: Int
init {
this.name = name
this.age = age
}
fun displayInfo() {
println("์ด๋ฆ์ ${name} ์
๋๋ค")
println("๋์ด๋ ${age} ์
๋๋ค")
}
}
- ์ค์ฝํ ํจ์ ์์์ ํธ์ถํ ๋์์ this๋ก ์ฌ์ฉ
- with์ ๋ฌ๋ฆฌ null์ฒดํฌ๋ฅผ ์ํํ ์ ์์ผ๋ฏ๋ก ๋์ฑ ์์ ํ๊ฒ ์ฌ์ฉ๊ฐ๋ฅ
- ํด๋์ค ๋ด๋ถ์ ํจ์๋ฅผ ์ฌ์ฉํ๋ ๊ฒ๊ณผ ๋์ผํ ํจ๊ณผ์ด๊ธฐ ๋๋ฌธ์, this๋ฅผ ์๋ตํ๊ณ ๋ฉ์๋๋ ํ๋กํผํฐ ๋ฐ๋ก ์ฌ์ฉ ๊ฐ๋ฅ
also
fun main() {
var student = Student("์ฐธ์", 10)
var result = student?.also {
it.age = 50
}
result?.displayInfo()
student.displayInfo()
}
class Student(name: String, age: Int) {
var name: String
var age: Int
init {
this.name = name
this.age = age
}
fun displayInfo() {
println("์ด๋ฆ์ ${name} ์
๋๋ค")
println("๋์ด๋ ${age} ์
๋๋ค")
}
}
- ์ค๊ดํธ ๋ธ๋ก์์ it์ผ๋ก ์์ ์ ๊ฐ์ฒด๋ฅผ ์ ๋ฌํ๊ณ ๊ฐ์ฒด๋ฅผ ๋ฐํ
- apply์ ํจ๊ป ์์ฃผ ์ฌ์ฉ
apply
fun main() {
var student = Student("์ฐธ์", 10)
var result = student?.apply {
student.age = 50
}
result?.displayInfo()
student.displayInfo()
}
class Student(name: String, age: Int) {
var name: String
var age: Int
init {
this.name = name
this.age = age
}
fun displayInfo() {
println("์ด๋ฆ์ ${name} ์
๋๋ค")
println("๋์ด๋ ${age} ์
๋๋ค")
}
}
- ์ค๊ดํธ ๋ธ๋ก์์ this๋ก ์์ ์ ๊ฐ์ฒด๋ฅผ ์ ๋ฌํ๊ณ ๊ฐ์ฒด๋ฅผ ๋ฐํ
- ์ฃผ๋ก ๊ฐ์ฒด์ ์ํ๋ฅผ ๋ณํ์ํค๊ณ ๋ฐ๋ก ์ ์ฅํ๊ณ ์ถ์๋ ์ฌ์ฉ
this์ it์ผ๋ก ๊ตฌ๋ถํ๊ธฐ
this๋ก ์ฌ์ฉ๋๋ ์ค์ฝํ ํจ์: run, apply, with
var list = mutableListOf("Scope", "Function")
โ
list.apply {
val listSize = size
println("๋ฆฌ์คํธ์ ๊ธธ์ด apply = $listSize")
}
โ
with (list){
val listSize = size
println("๋ฆฌ์คํธ์ ๊ธธ์ด with = $listSize")
}
- apply์ with์ ์ฌ์ฉ ์์ / example.apply, with (example)
- ์ค์ฝํ ํจ์ ์์์ this๋ก ์ฌ์ฉ๋๊ธฐ ๋๋ฌธ์ ๋ฉ์๋๋ ํ๋กํผํฐ๋ฅผ ์ง์ ํธ์ถ
๐ก ํธ์ถ ๋์์ด null์ผ ๊ฒฝ์ฐ?
- with์ ์ค์ฝํ ํจ์์ง๋ง, ์์ 2๊ฐ์๋ ๋ค๋ฅด๊ฒ ํ์ฅ(Extension) ํจ์๊ฐ ์๋๊ธฐ ๋๋ฌธ์ ์ผ๋ฐ ํจ์์ฒ๋ผ ์ฌ์ฉ๋จ
- ๋ฐ๋ผ์ ํธ์ถํ๋ ๋์์ด null์ผ ๊ฒฝ์ฐ์๋ with๋ณด๋ค๋ apply๋ run์ ์ฌ์ฉํ๋ ๊ฒ์ด ํจ์จ์
- target?.apply { /* ์ฝ๋ */ }
it์ผ๋ก ์ฌ์ฉ๋๋ ์ค์ฝํ ํจ์: let, also
var list = mutableListOf("Scope", "Function")
list.let { target -> // it์ target ๋ฑ๊ณผ ๊ฐ์ด ๋ค๋ฅธ ์ด๋ฆ์ผ๋ก ๋ณ๊ฒฝ ๊ฐ๋ฅ
val listSize = target.size // target์ผ๋ก ๋ณ๊ฒฝํ๊ธฐ์ ๋ฉค๋ฒ ์ ๊ทผ์ target.์์ฑ
println("๋ฆฌ์คํธ์ ๊ธธ์ด let = $listSize")
}
โ
list.also {
val listSize = it.size
println("๋ฆฌ์คํธ์ ๊ธธ์ด also = $listSize")
}
- let๊ณผ also์ ์ฌ์ฉ์์ / example.let, example.also
๋ฐํ๊ฐ์ผ๋ก ๊ตฌ๋ถํ๊ธฐ
- ๋์ผํ๊ฒ this๋ก ์ฌ์ฉ๋๋ ํจ์๋ผ๋, ๋์ ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํด์ ๊ฐ์ ๋ฐํํ ๊ฒฝ์ฐ์๋ ์ฉ๋๊ฐ ๋ฌ๋ผ์ง
- ๊ฒฐ๊ด๊ฐ์ ๋ฐํํ ๊ฒฝ์ฐ, ์ค์ฝํ๊ฐ ์ข ๋ฃ๋๋ ์์ ์์์ ๋ฐํ๊ฐ์ด ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ์๋ก ๋ค๋ฅธ ์ญํ ์ ์ค์ฝํ ํจ์๊ฐ ํ์
ํธ์ถ ๋์์ธ this ์์ฒด๋ฅผ ๋ฐํํ๋ ์ค์ฝํ ํจ์: apply, also
var list = mutableListOf("Scope", "Function")
โ
val afterApply = list.apply {
add("Apply")
count()
}
println("๋ฐํ๊ฐ apply = $afterApply") // ๋ฐํ๊ฐ apply = [Scope, Function, Apply]
โ
val afterAlso = list.also {
it.add("Also")
it.count()
}
println("๋ฐํ๊ฐ also = $afterAlso") // ๋ฐํ๊ฐ also = [Scope, Function, Apply, Also]
- apply, also๋ฅผ ์ฌ์ฉํ๋ฉด ์ค์ฝํ ํจ์ ์์์ ์ฝ๋๊ฐ ๋ชจ๋ ์๋ฃ๋ ํ ์๊ธฐ ์์ ์ ๋๋๋ ค ์ค
- ๋ค์ ์์ ์์ apply ์ค์ฝํ์ ๋ง์ง๋ง ์ค์์ count()๋ฅผ ํธ์ถํ์ง๋ง ๋ง์ง๋ง ์ฝ๋์ ์๊ด์์ด ๊ทธ๋ฅ MutableList ์์ ์ ๋๋ ค์ฃผ๊ธฐ ๋๋ฌธ์ Scope, Function์ Apply๊ฐ ์ถ๊ฐ๋ ๊ฐ์ด ์ถ๋ ฅ๋จ
- apply ํจ์๋ ๋๋ค ๋ธ๋ก์ ๋ง์ง๋ง ํํ์์ธ count()๋ฅผ ์คํํ์ง๋ง ํด๋น ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ์ง ์์. ๋ฐ๋ผ์ afterApply์๋ count() ํจ์์ ๋ฐํ๊ฐ์ด ํฌํจ๋์ง ์์
- also ํจ์๋ ๋๋ค ๋ธ๋ก์ ์ธ์๋ก ์ ๋ฌ๋ ๊ฐ์ฒด๋ฅผ ๋ฐํํจ. ๋ฐ๋ผ์ also ํจ์ ๋ด๋ถ์์ count()๋ฅผ ํธ์ถํ์ฌ๋ ํด๋น ๊ฒฐ๊ณผ๊ฐ ๋ฐํ๋์ง ์๊ณ ์๋์ ๋ฆฌ์คํธ๋ฅผ ๊ทธ๋๋ก ๋ฐํํจ.
๋ง์ง๋ง ์คํ ์ฝ๋๋ฅผ ๋ฐํํ๋ ์ค์ฝํ ํจ์: let, run, with
var list = mutableListOf("Scope", "Function")
โ
val lastCount = list.let {
it.add("Run")
it.count()
}
println("๋ฐํ๊ฐ let = $lastCount") // ๋ฐํ๊ฐ let = 3
โ
val lastItem = list.run {
add("Run")
get(size-1)
}
println("๋ฐํ๊ฐ run = $lastItem") // ๋ฐํ๊ฐ run = Run
โ
val lastItemWith = with(list){
add("With")
get(size-1)
}
println("๋ฐํ๊ฐ with = $lastItemWith") // ๋ฐํ๊ฐ with = With
- let, run, with์ ๊ฒฐ๊ด๊ฐ์ ๋ฐํํ๋ ๊ฒฝ์ฐ์๋ ์์ 2๊ฐ์๋ ์์ ํ ๋ค๋ฅธ ๊ฒฐ๊ณผ๊ฐ ๋์ฌ ์ ์์
- ์๊ธฐ ์์ ์ด ์๋ ์ค์ฝํ์ ๋ง์ง๋ง ์ฝ๋๋ฅผ ๋ฐํ
- let ํจ์:
let ํจ์๋ ๋๋ค ๋ธ๋ก์ ์์ ๊ฐ์ฒด๋ฅผ ์ธ์๋ก ์ ๋ฌํ๊ณ , ๋๋ค ๋ธ๋ก์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํ
๋๋ค ๋ธ๋ก ๋ด๋ถ์์ it์ ์ฌ์ฉํ์ฌ ์์ ๊ฐ์ฒด์ ์ ๊ทผ
์ฒซ ๋ฒ์งธ๋ก ์์ ๊ฐ์ฒด์ธ list์ "Run"์ ์ถ๊ฐํ๊ณ , ๊ทธ ํ์ ์์ ๊ฐ์๋ฅผ ๋ฐํ
๋ฐ๋ผ์ ๋ฐํ๊ฐ์ ์ถ๊ฐ ํ์ ๋ฆฌ์คํธ์ ์์ ๊ฐ์์ธ 3 - run ํจ์:
run ํจ์๋ ์์ ๊ฐ์ฒด์ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ํํ๋ก ์ฌ์ฉ
๋๋ค ๋ธ๋ก ๋ด๋ถ์์ this๋ฅผ ์ฌ์ฉํ์ฌ ์์ ๊ฐ์ฒด์ ์ ๊ทผ
run ํจ์์ ๊ฒฐ๊ณผ๋ ๋๋ค ๋ธ๋ก์ ๋ง์ง๋ง ํํ์์ ๊ฒฐ๊ณผ
๋๋ค ๋ธ๋ก ๋ด๋ถ์์ "Run"์ ๋ฆฌ์คํธ์ ์ถ๊ฐํ ํ, ๋ฆฌ์คํธ์ ๋ง์ง๋ง ์์๋ฅผ ๋ฐํ
๋ฐ๋ผ์ ๋ฐํ๊ฐ์ ์ถ๊ฐ ํ์ ๋ฆฌ์คํธ์ ๋ง์ง๋ง ์์์ธ "Run" - with ํจ์:
with ํจ์๋ ์์ ๊ฐ์ฒด์ ํจ๊ป ํธ์ถ
๋๋ค ๋ธ๋ก ๋ด๋ถ์์๋ ์์ ๊ฐ์ฒด๋ฅผ this๋ฅผ ์ฌ์ฉํ์ฌ ์ ๊ทผํ ํ์ ์์ด ์ง์ ์ ๊ทผ
with ํจ์์ ๊ฒฐ๊ณผ๋ ๋๋ค ๋ธ๋ก์ ๋ง์ง๋ง ํํ์์ ๊ฒฐ๊ณผ
with ํจ์ ๋ด๋ถ์์ "With"๋ฅผ ๋ฆฌ์คํธ์ ์ถ๊ฐํ ํ, ๋ฆฌ์คํธ์ ๋ง์ง๋ง ์์๋ฅผ ๋ฐํ
๋ฐ๋ผ์ ๋ฐํ๊ฐ์ ์ถ๊ฐ ํ์ ๋ฆฌ์คํธ์ ๋ง์ง๋ง ์์์ธ "With"
์์ ๊ฐ์ฒด, ๋๋ค์์ ๊ด๊ณ
// ์์ ๊ฐ์ฒด ์์ฒด๋ฅผ ๋๋ค์ ์์ ๊ฐ์ฒด๋ก ์ ๋ฌํ๋ ๋ฐฉ๋ฒ
public inline fun <T, R> T.run(block: T.() -> R): R
public inline fun <T> T.apply(block: T.() -> Unit): T
public inline fun <T, R> with(receiver: T, block: T.() -> R): R
// ์์ ๊ฐ์ฒด๋ฅผ ๋๋ค์ ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌ
public inline fun <T> T.also(block: (T) -> Unit): T
public inline fun <T, R> T.let(block: (T) -> R): R
- T๋ ์์ ๊ฐ์ฒด๋ฅผ ์๋ฏธ
- block: ๋ด๋ถ๋ ๋๋คํจ์์ ์์ค์ฝ๋
- ์์ ๊ฐ์ฒด๋ it์ผ๋ก ์ฌ์ฉํ ์ ์์, ๊ทธ๋ฌ๋ ๋ชจ๋ ์์ ๊ฐ์ฒด๋ฅผ it์ผ๋ก ํ์ฉํ๋ฉด ๋ฌธ์ ๊ฐ ์๊ธธ ์ ์์
Child Function์์ Shadow๊ฐ ๋์ด์ ์ ๋๋ก ์ฐธ์กฐํ์ง ๋ชปํ ์ ์์ด์
๋ฐ๋ผ์ it์ ๋ค๋ฅธ ์ด๋ฆ์ผ๋ก ๋ณ๊ฒฝํด์ ์ฌ์ฉํ๊ธฐ๋ ํจ
// Scope Function์ ์ค์ฒฉ์ผ๋ก ์ฌ์ฉํ ๊ฒฝ์ฐ ๋๊ฐ ๋๊ตฌ์ ๋ฒ์์ธ์ง ์์ ์๋ค!
// Implicit parameter 'it' of enclosing lambda is shadowed ๊ฒฝ๊ณ ๋ฐ์!
data class Person(
var name: String = "",
var age: Int? = null,
var child: Person? = null
)
// ์๋ชป๋ ์์
Person().also {
it.name = "ํ์๋ด"
it.age = 40
val child = Person().also {
it.name = "ํ๊ธธ๋" // ๋๊ตฌ์ it์ธ์ง ๋ชจ๋ฅธ๋ค!
it.age = 10 // ๋๊ตฌ์ it์ธ์ง ๋ชจ๋ฅธ๋ค!
}
it.child = child
}
// ์์ ํ ์์
Person().also {
it.name = "ํ์๋ด"
it.age = 40
val child = Person().also { c ->
c.name = "ํ๊ธธ๋"
c.age = 10
}
it.child = child
}
Scope์์ ์ ๊ทผ๋ฐฉ์ this | Scope์์ ์ ๊ทผ๋ฐฉ์ it | |
๋ธ๋ก ์ํ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํ | run, with | let |
๊ฐ์ฒด ์์ ์ ๋ฐํ | apply | also |
๋ฐ์ํ
๐ฌ C O M M E N T