이 글은 udemy 강의를 참고하여 작성하였습니다.
작성자 : 김예진
개발환경은 Windows, Android Studio입니다.
1. 스코프 함수
* 스코프 함수
스코프 함수(영역 함수)는 함수형 언어의 특징을 좀 더 쉽게 활용할 수 있도록 객체의 컨텍스트를 유지하면서 코드 블록을 받아 실행시키는 함수입니다. 스코프 함수는 대개 코드를 간결하게 만들어주는 기능을 수행합니다.
스코프 함수의 종류는 5가지로 run, let, apply, else 그리고 with이 있습니다.
1. run
fun studyRun(){
val phones = mutableListOf("010-1234-5678", "010-3456-8978", "010-1010-1001")
val resultRun = phones.run{ //run 블록 안에서는 내가 다루고자 하는 변수의 타입을 통째로 넘겨받음
add("010-2345-9871") //phone의 네번째 값 추가
}
}
run은 내가 다루고자 하는 객체 뒤에 .run{} 을 붙여 사용합니다. 블럭 안에서 다양한 메서드를 호출할 수 있는데, 호출 시 객체를 명시할 필요가 없습니다.
fun studyRun(){
val phones = mutableListOf("010-1234-5678", "010-3456-8978", "010-1010-1001")
phones.add("010-2345-9871")
}
위의 코드 속 phones.add("010-2345-9871")은 우리가 기존에 사용하던 메서드 호출 방식으로, 메서드를 호출할 때 늘 객체도 함께 호출해야 합니다. 만약 호출하는 메서드가 늘어나거나 객체명이 길어지면 우리는 매번 객체명을 반복해 작성하는 데에 번거로움을 느끼게 될 것입니다. 하지만 스코프 함수에서는 객체명을 .run 앞에 한 번 적어주기만 하면 블럭 안에서 메서드만을 사용하여 객체를 다룰 수 있습니다. (this를 참조하는 원리를 활용하지만 생략 가능) 이는 스코프 함수의 사용 이유 중 하나로, 불필요한 반복 작업을 줄여주고 코드 간소화가 가능함을 보여줍니다. 이렇게 블럭 내에서 메서드가 호출되고 난 뒤의 최종값이 resultRun이라는 변수에 리턴됩니다.
2. let
let은 run과 유사하지만 블록 내에서 다룰 변수의 경로를 명확하게 하기 위해 it을 참조합니다.
fun studyRun(){
val user = User()
val resultRun = user.characters.run{
add(Character("Yejin", 23))
add(Character("Sangwoo", 25))
add(Character("Jaeyoung", 27))
}
}
class User{
var characters = mutableListOf<Character>()
}
data class Character(
var name: String = "",
var level: Int = 0
)
위의 예시는 run을 사용해 user 객체의 characters 배열에 캐릭터의 정보를 추가하는 코드입니다. 이처럼 여러 클래스가 중첩되어 있는 경우에 블록 내에서 호출하는 메서드가 정확히 어떤 객체에서 이루어지는지 명시하고 싶을 때 let을 사용합니다. 위의 코드에서 스코프 함수가 사용된 부분만 let을 활용해 바꿔보겠습니다.
val resultLet = user.characters.let{ characters -> //let 스코프 안에서는 user.characters를 characters로 사용하겠다는 선언
characters.add(Character("Yejin", 23))
characters.add(Character("Sangwoo", 25))
characters.add(Character("Jaeyoung", 27))
}
이처럼 let은 예약어를 설정해 메서드 내에서 객체를 명확하게 표기하고, run은 자기 자신을 사용한다는 차이점을 확인할 수 있습니다. let 역시 resultLet에 최종값이 리턴됩니다.
3. apply
val resultApply = user.characters.apply{
add(Character("Yejin", 23))
add(Character("Sangwoo", 25))
add(Character("Jaeyoung", 27))
}
apply는 run과 사용법이 동일합니다. 다만 apply는 코드의 마지막 줄과 관계 없이 메서드가 실행되고 난 뒤 변경된 객체를 리턴합니다.
val resultRun = user.characters.run{
add(Character("Yejin", 23))
add(Character("Sangwoo", 25))
add(Character("Jaeyoung", 27))
size
}
print(resultRun)
//출력: 3
val resultApply = user.characters.apply{
add(Character("Yejin", 23))
add(Character("Sangwoo", 25))
add(Character("Jaeyoung", 27))
size
}
print(resultApply)
//출력: [Character(name=Yejin, level=23), Character(name=Sangwoo, level=25), Character(name=Jaeyoung, level=27)]
run은 블록 내에 메서드가 실행되고 난 뒤 마지막 문장인 size에 의해 characters 배열의 사이즈인 3을 리턴하지만, apply는 블록 내에 메서드가 실행되고 난 뒤 변경된 객체의 값만을 리턴합니다.
4. also
val resultAlso = user.characters.also{ characters ->
characters.add(Character("Yejin", 23))
characters.add(Character("Sangwoo", 25))
characters.add(Character("Jaeyoung", 27))
}
also는 let과 사용법이 동일하며 run-apply의 관계처럼 let과 다른 리턴값을 갖습니다. let은 최종값을, also는 객체를 반환합니다.
val resultLet = user.characters.let{ characters ->
characters.add(Character("Yejin", 23))
characters.add(Character("Sangwoo", 25))
characters.add(Character("Jaeyoung", 27))
characters.size
}
print(resultLet)
//출력: 3
val resultAlso = user.characters.also{ characters ->
characters.add(Character("Yejin", 23))
characters.add(Character("Sangwoo", 25))
characters.add(Character("Jaeyoung", 27))
characters.size
}
print(resultAlso)
//출력: [Character(name=Yejin, level=23), Character(name=Sangwoo, level=25), Character(name=Jaeyoung, level=27)]
5. with
with은 뷰 바인딩에 자주 사용되는 함수입니다. 사용 방법은 위에서 학습한 다른 스코프 함수들과 유사합니다.
class MainActivity : AppCompatActivity(){
val binding by lazy (ActivityMainBinding.inflate(layoutInflater))
override fun onCreate(savedInstanceState: Bundle?){
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
binding.button.setOnClickListener{} //기존의 바인딩 방식
binding.imageview.setImageLevel(50)
binding.textView.text = "반가워"
}
}
예시에서는 위젯을 세 가지만 사용하였지만, 개수가 늘어갈수록 우리는 번거롭게 binding 키워드를 반복하여 작성하게 됩니다. 이 때 with을 사용하여 아래 세 줄의 코드를 다음과 같이 간단하게 만들어줄 수 있습니다.
with(binding){
button.setOnClickListener { }
imageView.setImageLevel(50)
textView.text = "반가워"
}
이처럼 with를 사용하면 더욱 간소화된 코드로 코틀린 익스텐션에 접근하는 것처럼 기존 위젯에 접근할 수 있게 됩니다.
'GDSC HUFS 3기 > Android with Kotlin Team 4' 카테고리의 다른 글
[4팀] 12~16. 레이아웃, 리스너, 버튼과 스트링 소스, Dimen 리소스, color 리소스, 텍스트뷰 (0) | 2021.10.30 |
---|---|
[4팀] 11. (2) Kotlin을 위한 기본 문법 : 화면에 그려지는 디자인 요소 위젯 (0) | 2021.10.29 |
[4팀] Section 7 - (2) : Kotlin - Object Oriented Programming (0) | 2021.10.05 |
[4팀] Section 7 - (1) : Kotlin - Object Oriented Programming (0) | 2021.10.05 |
[4팀] Section 6 : Kotlin - Decisions and Loops (2) | 2021.10.04 |