고차 함수
- 다른 함수를 인자로 받거나 함수를 반환하는 함수
- filter, map, with 등
// 함수도 타입이 존재한다. 타입을 명시하면 실제 람다식은 타입 추론이 가능하다.
val sum: (Int, Int) -> Int = { x, y -> x + y }
// nullable도 가능
val sumNullable: (Int, Int) -> Int? = { x, y -> x + y }
val actions: () -> Unit = { println(123) }
// 함수 전체에 대해서도 nullable을 정의할 수 있다.
val actionsNullable: (() -> Unit)? = { println(123) }
인라인 함수
- 람다가 생성되는 시점마다 새로운 익명 클래스 객체 생성. -> 성능 저하
- inline 변경자를 활용하여 해당 인라인 함수 호출하는 곳에 함수 본문에 해당하는 바이트 코드를 복사하여 컴파일
fun main() {
// Closeable을 구현체들은 inline 확장함수인 use를 사용할 수 있다.
// use 인라이닝 함수는 내부적으로 자원 할당을 해제해주기 때문에 간편히 Closeable 구현체를 사용할 수 있다.
BufferedReader(FileReader(""))
.use { doRun(it) }
}
fun doRun(bufferedReader: BufferedReader): List<String> {
return listOf(bufferedReader.readLine())
}
제네릭스
- 코틀린은 raw 타입을 허용하지 않으므로 제네릭 타입의 인자를 컴파일러가 알 수 있게 해줘야 함.
// 타입 파라미터에 여러 제약을 가할 수 있다.
// T 타입은 반드시 CharSequence와 Appendable을 구현한 구현체여야 한다.
fun <T> ensureTrailingRerioid(seq: T)
where T : CharSequence, T : Appendable {
if (!seq.endsWith('.')) {
seq.append('.')
}
}
// 타입파라미터는 nullable하므로 null 불가능하게 막을 수 있다.
fun <T : Any> test(t: T): Nothing = TODO()