Kotlin Pair, Triple 그리고 Scope 함수 정리
11 Oct 2022패스트 캠퍼스 실무 프로젝트로 배우는 Kotlin & Spring 강의 정리
Pair & Triple
- 코틀린 표준 라이브러리에서 제공하는 데이터 클래스
- 각각 두 값, 세 값을 저장 가능
-
toString()
,toList()
제공 - first, second, third(triple)은 불변 속성
-
componentN 메서드 가짐
- 배열이나 리스트에서도 구조 분해 할당 사용 가능하며 내부에서는 componentN 메서드 이용
- 구조 분해 할당은 각 프로퍼티의 위치에 따라 결정됨
fun main() {
val pair = Pair("A", 1)
println(pair.second + 2) // 3
// pair.first = "B" 불변이므로 컴파일 오류 발생
val newPair = pair.copy(first = "B") // copy 메서드 이용해서 새 인스턴스 생성
val pair2 = "One" to 1 // 중위 연산자로 생성 가능
val map = mutableMapOf(Pair("Two", 2)) // map 생성할 때 Pair 사용 가능
val triple = Triple("a", "b", "c")
val (a, b, c) = triple // 구조 분해 할당
val triple2 = Triple("Tom", 25, "UK")
val (name: String, age: Int, country: String) = triple2
}
Scope Functions
- 코틀린 표준 라이브러리에서 객체의 컨텍스트 안에서 코드 블록을 실행하기 위해서만 존재하는 함수
- 스코프 함수를 잘 사용하면 불필요한 변수 선언없이 더 간결하고 읽기 쉬운 코드 작성 가능
- 스코프 함수의 코드 블록 내부에서는 수신자 객체에 접근 가능
- 변수명을 사용하지 않고도 객체 접근 가능
- 수신자 객체는 람다식 내부에서 사용할 수 있는 객체의 참조
- 스코프 함수를 사용하면 수신자 객체에 대한 참조로
this
또는it
사용 this
는 키워드로서 변수 이름으로 사용 불가it
은 소프트 키워드로 변수 이름으로 사용 가능
함수명 | 수신자 객체 참조 방법 | 반환 값 | 확장 함수 여부 |
---|---|---|---|
let | it | 함수의 결과 | O |
run | this (생략 가능) | 함수의 결과 | O |
with | this (생략 가능) | 함수의 결과 | X |
apply | this (생략 가능) | 컨텍스트 객체 | O |
also | it | 컨텍스트 객체 | O |
- let
- null이 아닌 경우, 사용될 로직을 작성한 후 새로운 결과를 반환할 때 사용
- let 함수 구문의 가장 마지막이 반환값이 됨
- let 함수 내부에 중첩 let 함수 구문 가능
- 중첩 함수가 많아지면 가독성이 떨어지므로 if-else 구문이 더 나을 수 있음
fun main{
val str1: String? = null
str1?.let { println(it) } // 안전연산자와 함께 사용하여 let 함수가 실행되지 않음
val str2: String? = "Hi"
str2?.let { println(it) } // Hi
val result = str2?.let {
println(it)
1
}
println(result) // 1
str2.let {
val abc: String = "abc"
abc.let {
val def: String = "def"
def.let { println("not null") }
}
} // not null
}
- run
- 수신 객체 프로퍼티를 구성하거나 새로운 결과를 반환할 때 사용
- 함수 내부의 마지막이 반환 값
class DbClient {
var url: String? = null
var username: String? = null
var password: String? = null
fun connect(): Boolean {
println("Connected")
return true
}
}
fun main() {
// val config = DbClient()
// config.url = "localhost:3306"
// config.username = "mysql"
// config.password = "1234"
// val connected = config.connect()
// run 사용해서 위의 코드 구현
val connected = DbClient().run {
url = "localhost:3306"
username = "mysql"
password = "1234"
connect()
}
println(connected) // true
}
- with
- 결과 반환없이 내부에서 수신 객체를 이용해서 다른 함수를 호출할 때 사용
- 다른 함수와 다르게 확장 함수가 아님
- with 함수에 변수에 대한 참조를 넣음
fun main() {
val str = "Hi"
with(str) {
println("length = $length")
}
val length = with(str) { length }
}
- apply
- 수신 객체 프로퍼티를 구성하고 수신 객체의 결과를 그대로 반환하고 싶을 때 사용
class DbClient {
var url: String? = null
var username: String? = null
var password: String? = null
fun connect(): Boolean {
println("Connected")
return true
}
}
fun main() {
val client: DbClient = DbClient().apply {
url = "localhost:3306"
username = "mysql"
password = "1234"
}
println("client = $client") // client = DbClient@279f2327
client.connected.run { println(this) } // connect 메서드 반환값인 true
}
- also
- 부수 작업을 수행하거나 전달받은 수신 객체를 그대로 결과로 반환하고 싶을 때 사용
class User(val name: String, val password: String) {
fun validate() {
if (name.isNotEmpty() && password.isNotEmpty()) {
println("Validated")
} else {
println("Not Validated")
}
}
}
fun main() {
User("Tom", "1234").also {
it.validate() // "Validated"
it.printName() // Tom
}
}