Kotlin basic method
표준 라이브러리
람다식을 사용하는 코틀린의 표준 라이브러리에서 let(), apply(), with(), also(), run() 등 여러 가지 표준 함수를 활용해 코드의 효율을 높입니다. 이러한 함수를 통해 기존의 복잡한 코드를 단순화하고 효율적으로 만들 수 있다.
let()
let()함수는 함수를 호출하는 객체 T를 이어지는 block의 인자로 넘기고 block의 결과값 R을 반환
** 람다식에서 it과 this를 인자로 받을 경우 값을 가져오는 방식이 다르다. it은 인자를 복제하여 후 처리를 진행하고, this는 인자의 참조값을 그대로 후 처리를 진행한다. **
-예제 코드
val score: Int? = 32
...
// let을 사용해 null 검사를 제거
fun checkScoreLet() {
score?.let { println("Score: $it") } // ① it은 32를 반환
val str = score.let { it.toString() } // ② 32를 String으로 변환 후 반환
println(str)
}
checkScoreLet()
let 함수의 체이닝
여러 메서드를 연속적으로 호출한다.
var a = 1
var b = 2
a = a.let { it + 2 }.let { // it은 1을 복제
val i = it + b // it은 위에서 처리된 결과 값 3을 복제한다.
i // 마지막 식 반환
}
println(a) //5
let 함수의 중첩
var x = "Kotlin"
x.let { outer ->
outer.let { inner ->
print("Inner is $inner and outer is $outer") // it 을 사용하지않고 명시적이름을 사용 inner & outer 둘다 "Kotlin"
}
}
반환값은 바깥쪽의 람다식에만 적용
fun main() {
var x = "Kotlin"
x = x.let { outer ->
outer.let { inner ->
println("Inner is $inner and outer is $outer")
"Inner String" // 반환 되지 않음
}
"Outer String" // 해당 문자열이 x에 반환되어 할당
}
println(x) // Outer String
}
사용 예시
1. 안드로이드 커스텀 뷰 padding 값 지정
val padding = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 16f, resources.displayMetrics).toInt()
setPadding(padding, 0, padding, 0)
위의 코드를 let을 사용하여 간략하게 만들 수 있다.
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16f,
resources.displayMetrics).toInt().let{ padding ->
setPadding(padding, 0, padding, 0) // 계산된 값을 padding 이라는 이름의 인자로 받음
}
위와 같은 코드이며 it으로 사용하였을 경우
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16f,
resources.displayMetrics).toInt().let{
setPadding(it, 0, it, 0) // padding 이라는 이름 대신 it 사용
}
2. null 검사
세이프 콜(?.)과 함께 사용하면 간략하게 검사 가능
var obj: String? // null 일 수 있는 변수
...
if(null != obj){
Toast.makeText(applicationContext, obj, Toast.LENGTH_LONG).show()
}
위처럼 if(null != obj)
대신 let 사용 가능
obj?.let{ // 세이프 콜 사용
Toast.makeText(applicationContext, it, Toast.LENGTH_LONG).show()
}
만약 else문이 포함되었다면
val firstName: String?
var lastName: String
...
if (null != firstName){
print("$firstName $lastName")
}else{
print("$lastName")
}
위 코드를 한줄로 줄일 수 있다.
firstName?.let{print("$it $lastName")} ?: print("$lastName")
also()
also()는 함수를 호출하는 객체 T를 이어지는 block에 전달하고 객체 T 자체를 반환
public inline fun <T> T.also(block: (T) -> Unit): T { block(this); return this }
예제
fun main() {
data class Person(var name: String, var skill: String)
val person = Person("Killdong", "swing")
val a = person.also{
it.skill = "Java"
"Success" //마지막 식은 반환되지 않음 (무의미한 식)
}
println("a: $a") // a: Person(name=Killdong, skill=Java)
println("person: $person") //person: Person(name=Killdong, skill=Java)
}
apply()
apply()함수는 also()함수와 마찬가지로 호출하는 객체 T를 이어지는 block으로 전달하고 객체 자체인 this를 반환. 보통 객체 초기화 작업을 수행하는 경우 효과적으로 사용
fun main() {
data class Person(var name: String, var skills : String)
var person = Person("Kildong", "Kotlin")
// 여기서 this는 person 객체를 가리킴
person.apply { this.skills = "Swift" }
println(person) // Person(name=Kildong, skills=Swift)
val retrunObj = person.apply {
name = "Sean" // ① this는 생략할 수 있음
skills = "Java" // this 없이 객체의 멤버에 여러 번 접근
}
println(person) // Person(name=Sean, skills=Java)
println(retrunObj) // Person(name=Sean, skills=Java)
}
run()
run()함수는 인자가 없는 익명 함수처럼 동작하는 형태로 단독 사용하거나 확장 함수 형태로 호출하는 형태 두 가지로 사용 가능
1. 독립적 사용
독립적으로 사용할 때는 block에 처리할 내용을 넣어주며 마지막 식이 반환
val a = 10
skills = run {
val level = "Kotlin Level:" + a
level // 마지막 표현식이 반환됨
}
할당 없이 사용할 때는 체이닝을 사용해 특정 결과에 대한 메서드를 실행 가능
run {
if (firstTimeView) introView else normalView
}.show()
2. 확장 함수로 사용
val retrunObj = person.apply {
name = "Sean" // ① this는 생략할 수 있음
skills = "Java" // this 없이 객체의 멤버에 여러 번 접근
"Success" // apply()는 반환값이 없음
}
println(person) // Person(name=Sean, skills=Java)
println(retrunObj) // Person(name=Sean, skills=Java)
val retrunObj2 = person.run {
this.name = "Kim"
this.skills = "Swift"
"Success"
}
println(person) // Person(name=Kim, skills=Swift)
println(retrunObj2) // Success
use()
보통 특정 객체가 사용된 후 닫아야 하는 경우가 생기는데 이때 use()를 사용하면 객체를 사용한 후 close() 등을 자동적으로 호출해 닫아 줄 수 있다.
fun main() {
PrintWriter(FileOutputStream("d:\\test\\output.txt")).use {
it.println("hello")
}
}
PrintWirter는 파일을 열거나 새롭게 생성해 파일에 출력할 수 있다. 이때 use를 사용하고 있는데 먼저 콘솔에 출력하듯 println을 통해 파일에 출력할 수 있게 된다. 이후 use는 열었던 파일을 닫아주는 작업을 내부에서 진행