# 람다
- 람다? -> 함수에 인자로 전달 할 수 있는 코드 모음
- JAVA 8 에서 사용할 수 있게된, 그 람다식... Kotlin에서도 사용할 수가 있다
- 람다는 메소드가 하나인 무명 객체를 대신 할 수 있다
람다 식 예시 in Kotlin
val lambda = { a : Int, b : Int -> a+b }
1) 중괄호로 표현
2) 파라미터 a, b와 실제 본문인 'a +b' 사이는 화살표로( ->) 구분한다
람다 식 변수 대입 예시
val sumLamda = { a : Int, b : Int -> a+b } //람다를 변수에 대입
println(sumLamda(10,20)) //변수에 저장된 람다 호출 방법 -> 30
람다의 다양한 표현 방식
Collection.kt의 'maxByOrNull' 함수는 인자값으로 람다를 함수를 받고 있다(age+grade의 값이 가장 큰 students를 반환)
studentMax1 ~ studentMax5 모두 동일한 의미, but 점진적으로 간결하게 표현되고 있다
val studentList = listOf<Student>(Student("Tina", 23, 4), Student("Scott", 24, 2))
//'age + grade' 합 max인 student 구하기
val studentMax1 =
// 인자로 람다식 넘기기
studentList.maxByOrNull({ student: Student -> student.age + student.grade })
val studentMax2 =
// 람다를 소괄호 밖으로 (함수의 마지막 인자가 람다일 경우만 가능)
studentList.maxByOrNull() { student: Student -> student.age + student.grade }
val studentMax3 =
// 람다를 소괄호 밖으로 옮기고 난 함수의 인자가 없을경우 함수 소괄호 생략 가능()
studentList.maxByOrNull { student: Student -> student.age + student.grade }
val studentMax4 =
// 파라미터 타입 생략(:Student 생략, 컴파일러가 추론 해 줌)
studentList.maxByOrNull { student -> student.age + student.grade }
val studentMax5 =
// 파라미터가 1개 이고, 컴파일러가 타입 추론이 가능 할 때, it 이라는 파라미터 이름으로 사용 가능
studentList.maxByOrNull { it.age + it.grade }
파라미터 변수 이름을 'it'으로 까지 간단히 표현 가능하지만, 변수 의미를 파악하기 어려우므로 상황에 따라 사용해야 한다
람다의 다양한 표현 방식(함수 인자가 2개 이상일 경우)
//람다 param 이름 명시해서 사용 transform ={ ~~ } -> 람다의 용도를 더욱 명확히
val info1 = studentList.joinToString( separator = " / ", transform = { student: Student -> "Student " + student.name })
// 람다를 소괄호 밖으로 (함수의 마지막 인자가 람다일 경우) -> 람다의 용도를 알기 어려워질 수도 있다
val info2 = studentList.joinToString(separator = " / ") { student: Student -> "Student " + student.name }
println("[Name Info] $info") //[Name Info] Student Tina / Student Scott
info1, info2 동일한 의미
info1 : 람다 인자에 이름 붙여 사용
info2 : 람다를 소괄호 밖으로 빼서 사용
람다 밖 함수의 변수 접근
람다 안에서 람다 밖의 함수의 변수에 접근이 가능하다
람다 안에서 람다 밖의 함수의 변수 수정도 가능하다
override fun onCreate(savedInstanceState: Bundle?) {
...
var local = "local" //람다 밖 변수
findViewById<TextView>(R.id.tv_hello).setOnClickListener {
println(local) //접근 가능
local = "local modified"//수정도 가능
}
}
이는 Java와 다른 점인데, Java의 경우에는 변수가 final이 아닐경우, 람다 밖 변수에 접근이 불가하다
Java에선 아래와 같이 컴파일 오류가 발생하는 것을 볼 수 있다.(Variable used in lambda expression should be final or effectively final)
final로 변경 하면 접근은 가능하지만 수정이 불가 해진다
이런 경우, final 배열에 수정하고자 하는 변수를 원소로 넣어서 사용하는 꼼수가 필요하기도 했다 (In JAVA)
결론 : Java와 달리 코틀린에서는 final변수가 아니더라도, 람다 밖 함수의 변수에 대해 접근/수정 가능하다
# 멤버 참조(member reference)
이미 만들어져 있는 함수를 전달 하고 싶을 때 사용한다
Student::name
1) :: (이중콜론)로 구분한다
2) 참조하려는 클래스
3) 참조하려는 클래스의 멤버(프로퍼티, 메소드)
멤버 참조 예시
data class Student constructor(val name: String, val age: Int)
fun Student.isAdult(): Boolean = age > 20
fun funPrint() = println("kotlin")
fun memberReferenceTest() {
//1)Student 생성자 참조
val createStudent = ::Student
val studentInstance = createStudent("Tina", 20)
//2)프로퍼티 참조
val getStudentAge = Student::age
println("Age1 : " + getStudentAge(studentInstance)) //instance를 넘겨줘야 한다 => 어떤 instance에 대한 멤버를 호출할 지 모르니까
//3)바운드 멤버 참조 : 나중에 해당 인스턴스에 대한 멤버를 참조해준다
val getStudentAge2 = studentInstance::age
println("Age2 : " + getStudentAge2()) // instance를 넘겨줄 필요가 없다 => 미리 지정한 instance에 대한 멤버를 호출해주기 때문에
//4)확장 함수 참조
val isAdult = Student::isAdult
println("isAdult : " + isAdult(studentInstance))
//5)최상위 함수 참조
run(::funPrint)
}
출처 : Kotlin In Action - 에이콘 출판사
(위 도서를 학습하고 개인 학습용으로 정리한 내용입니다)
'Kotlin' 카테고리의 다른 글
[Kotlin] 4.람다 In Collection(Sequence) (0) | 2021.11.17 |
---|---|
[Kotlin] 4.람다 In Collection (0) | 2021.11.16 |
[Kotlin] 3. Object (0) | 2021.11.15 |
[Kotlin] 3. Data Class, by (0) | 2021.11.07 |
[Kotlin] 3.Interface, Class, 변경자, 초기화블록, 추상 프로퍼티 (0) | 2021.11.06 |