[자바 개발자를 위한 코틀린 입문] 람다 다루기
by dev.hardy코틀린에서 람다를 다루는 방법
인프런에서 최태현 지식 공유자
님의자바 개발자를 위한 코틀린 입문
을 수강하며 정리한 내용 입니다.
하단에 강의 링크 있습니다.
자바에서 람다를 다루기 위한 노력
복잡한 조건에 따라 자꾸 메소드와 파라미터 늘리는 것만으로는 어려워지게 됨.
→ 인터페이스와 익명클래스를 사용하자!
→ 이렇게 해서 많은 것이 해결되었지만 아쉬운점이 있다.
익명 클래스
를 사용하는 것은 복잡하다.
이러한 어려움을 해결하기 이해 JDK 8부터 람다 (이름이 없는 함수) 등장!
Predicate, Consumer, Function 등 여러 인터페이스를 JDK 8에서 만들어 두었음.
그리고 간결한 스트림이 등장했다. (병럴처리에도 강점이 생김)
메소드 레퍼런스: 메소드를 넘기는 것 처럼
사용할 수 있다.
→ 메소드를 넘기는 것처럼의 이유 : Java에서 함수는 변수에 할당되거나 파라미터로 전달할 수 없다. (2급 시민)
→ 그러면? 메소드를 넘기는 것이 아니라 Predicate와 같은 함수형 인터페이스로 인해 가능한 것
코틀린에서의 람다
자바와는 근본적으로 다른 한 가지가 있다.
- 코틀린에서는 함수가 그 자체로 값이 될 수 있다.
- 변수에 할당할 수 있다.
- 파라미터로 넘길 수 있다.
예) 사과인지를 체크하는 함수를 변수에 할당하는 두 가지 방법 (람다를 만드는 방법) (1), (2)
fun main() {
val fruits = listOf(
Fruit("사과", 1000),
Fruit("사과", 1200),
Fruit("사과", 1200),
Fruit("사과", 1500),
Fruit("바나나", 3000),
Fruit("바나나", 3200),
Fruit("바나나", 2500),
Fruit("수박", 10000),
)
val isApple = fun(fruit: Fruit): Boolean { // (1)
return fruit.name == "사과"
}
val isApple2 = { fruit: Fruit -> fruit.name == "사과"} // (2)
}
(1) 일반적인 함수를 만드는 방법인데 함수이름
을 표시하지 않는다.
(2) 중괄호와 화살표를 사용하는 방법
예) 부르는 방법
isApple(fruits[0])
isApple.invoke(fruits[0])
그리고 함수를 할당안 변수에도 타입이 있다.
val isApple: (Fruit) -> Boolean = fun(fruit: Fruit): Boolean {
return fruit.name == "사과"
}
타입은 (Fruit) -> Boolean
이며, 파라미터로 Fruit을 받아 Boolean을 리턴하는 함수라는 뜻이 된다.
즉, 함수의 타입: (파라미터 타입…) → 반환타입
private fun filterFruits(
fruits: List<Fruit>,
filter: (Fruit) -> Boolean // (1)
): List<Fruit> {
val results = mutableListOf<Fruit>()
for (fruit in fruits) {
if (filter(fruit)) {
results.add(fruit)
}
}
return results
}
(1) 코틀린에서는 함수를 파라미터로 받을 수 있기때문에 파라미터: 함수 타입
으로 파라미터를 명시해서 함수를 받을 수 있다.
예) 사용해보자
fun main() {
val fruits = listOf(
Fruit("사과", 1000),
Fruit("사과", 1200),
Fruit("사과", 1200),
Fruit("사과", 1500),
Fruit("바나나", 3000),
Fruit("바나나", 3200),
Fruit("바나나", 2500),
Fruit("수박", 10000),
)
val isApple = {fruit: Fruit -> fruit.name == "사과"} // (1)
val results = filterFruits(fruits, isApple) // (2)
results.forEach {
println(it.name) // 사과만 나온다.
}
}
(1) (Fruit) → Boolean 함수타입인 함수를 만들어 준다.
(2) 만들어준 isApple이라는 함수를 파라미터로 넘긴다.
→ 익명함수이기 때문에 바로 함수를 변수에 할당하지 않고 그대로 넣어줄 수도 있다.
🤠 마지막 파라미터가 함수인 경우, 소괄호 밖에 람다 사용 가능
😸 람다를 작성할때, 람다의 파라미터를 it으로 직접 참조 가능
🤠 람다는 여러줄 작성 가능한데, return을 명시하지 않더라도 마지막 줄의 결과가 람다의 반환값이다!
filterFruits(fruits) {it.name == "사과"}
Closure
자바에서 람다는 외부 변수를 사용할 때 final인 변수나 실질적으로 final인 변수만 사용가능 했는데
코틀린에서는 아무 문제없이 사용할 수 있다.
var targetName = "사과"
targetName = "수박"
filterFruits(fruits) {it.name == targetName}
🧱 이것이 어떻게 가능할까?
→ 코틀린에서는 람다가 시작하는 지점에 참조하고 있는 변수들을 모두 포획
하여 그 정보를 가지고 있다.
이렇게 해야만, 람다를 진정한 일급 시민으로 간주할 수 있으며 이 데이터 구조를 Closure
라고 부른다.
**Closure**
: 람다가 실행되는 시점에 쓰고 있는 변수들을 모두 포획한 데이터 구조
다시 try with resources
fun readFile(path: String) {
BufferedReader(FileReader(path)).use { reader -> // (1)
println(reader.readLine())
}
}
(1) use를 주목
public inline fun <T : Closeable?, R> T.use(block: (T) -> R): R {
- Closeable 구현체에 대한 확장함수이다.
- inline 함수이다.
- 람다를 받게 만들어진 함수이다.
Reference:
자바 개발자를 위한 코틀린 입문
블로그의 정보
개발자 하디 : 기록저장소
dev.hardy