- 람다( Lambda )
- 람다 표현식의 줄인 말
- 익명 함수를 표현하는 방법
- 익명 함수란 실행 가능한 코드 블럭
- 람다 표현 방법
- 먼저 중괄호를 쓰고 함수의 파라미터를 쓴 뒤 '->' 기호로 실행되는 코드 블럭을 정의
val sum = {x:Int, y:Int -> x + y}
- 최상위 프로퍼티로 바로 접근 가능
- 코틀린이 함수를 일급 객체로 취급하기 때문
- 일급 객체( First Class Citizen )
- 변수와 자료 구조에 할당 가능해야 한다.
- 함수의 파라미터로 전달이 가능해야 한다.
- 함수의 반환값으로 전달이 가능해야 한다.
- 동등성 비교가 가능해야 한다.
// 람다표현식 내부에서 람다표현식을 반환
val exp = { x: Int, y: Int ->
{ z: Int -> (x + y)*z }
}
// exp2 --> { z: Int -> (x + y)*z }
val exp2 = exp( 1 , 2 )
// result --> ( 1 + 2 ) * 3
val result = exp2( 3 )
- Collection 의 함수형 API
- filter : 컬렉션에서 조건에 맞는 항목만 추출해 컬렉션을 반환한다.
- map : 컬렉션에 항목을 변환하여 새로운 걸렉션을 만들고 반환한다.
- flatmap : 컬렉션의 포함된 항목들을 평평하게 펼친 뒤 변환하여 새로운 컬렉션을 반환한다.
- find : 함수의 조건을 만족하는 항목 한 개를 반환한다.
- group by : 컬렉션을 여러 그룹으로 이뤄진 맵으로 변경한다.
@Test
fun testCollectionApi(){
// 컬렉션을 만든다
val list = listOf( 1, "2", 3, 4, 5.6, 7, 8 )
// filter : 컬렉션에서 특정 조건이 맞는 항목만 추출하여 새로운 컬렉션을 만든다. -> Int 타입만 추출한다.
println( list.filter{ item -> item is Int })
// [1, 3, 4, 7, 8]
// 람다 표현식에서 파라미터가 하나인 경우 생략이 가능하다.
// 파라미터는 it 키워드로 접근 가능
println( list.filter{ it is Int })
// [1, 3, 4, 7, 8]
// map : 컬렉션에서 아이템을 변환하여 새로운 컬렉션을 만든다. 아래코드는 String 의 컬렉션이 만들어진다.
println( list.map{ "value: ${it}" })
// [value: 1, value: 2, value: 3, value: 4, value: 5.6, value: 7, value: 8]
// filter 에서 반환된 컬렉션을 map 으로 변환
println( list.filter{ it is Int }.map{ "value: ${it}" })
// [value: 1, value: 3, value: 4, value: 7, value: 8]
// 아이템을 찾는다.
println( list.find{ it is Double })
// 5.6
// 컬렉션을 그룹화하여 Map<String, List<T>> 형태로 만든다. 아래코드는 각 아이템의 클래스 별로 그룹화 된다.
val map = list.groupBy { it.javaClass }
println( map )
// {class java.lang.Integer=[1, 3, 4, 7, 8], class java.lang.String=[2], class java.lang.Double=[5.6]}
// 컬렉션 안에 컬렉션이 있는 새로운 리스트를 만든다.
val list2 = listOf( listOf(1,2), listOf(3,4))
println( list2 )
// [[1, 2], [3, 4]]
// map 으로 항목을 변환한다.
println( list2.map{ "value: ${it}" })
// [value: [1, 2], value: [3, 4]]
// flatmap 으로 리스트를 평평하게 만들고 변환한다.
println( list2.flatMap { it.toList() })
// [1, 2, 3, 4]
//Assert.assertEquals(4, 2 + 2)
}
* 람다는 람다 표현식을 줄인 것으로 익명 함수를 표현하는 방법을 의미합니다.
* 코틀린은 중괄호 안에 파라미터와 실행 코드 블럭을 정의하여 람다식을 사용합니다.
* 코틀린의 컬렉션은 람다식을 활용하여 filter , map , flatmap , find , group by 등 유용한 함수를 제공합니다.
- 확장함수
- JAVA API 와 라이브러리 코드를 변경하지 않고도, 코틀린으로 만든 새로운 메소드나 함수를 마치 기존 JAVA API 에 원래 있었던 함수처럼 추가하여 사용 가능하다.
- 이미 정의된 클래스를 전혀 수정하지 않고도 클래스에 포함된 함수처럼 사용.
- public 으로 공개된 메소드와 멤버에 한정됨.
- Java 에는 확장함수 개념이 없기 때문에 '정적(static)함수' 일 뿐이다.
// String 클래스에 lastString 확장함수를 추가로 정의한다.
fun String.lastString(): String {
return this.get(this.length - 1).toString()
}
// String 수신객체 타입
// this 수신객체
* 확장 함수는 클래스 외부에서 정의하지만, 마치 클래스의 멤버 메소드처럼 사용할 수 있다.
* 확장 함수는 기존에 구현된 클래스를 전혀 건드리지 않고 기능을 확장할 수 있다.
* 확장 함수를 정의하기 위해서는 수신 객체의 타입을 함수 이름 앞에 적기만 하면 된다.
* 확장 함수를 Java 에서 호출할 때에는 'static(정적) 메소드'를 호출하는 것과 같다.
* 확장 함수는 실제로는 static 함수이며, 코틀린에서 멤버 ㅁ소드처럼 사용할 수 있게 해주는 문법적 편의이다.
* 확장 함수는 실제로는 외부에 선언된 static 함수이기 때문에, 상속되거나 오버라이드할 수 없다.
- 널 안전성( Null Safety )
- Type : Type 과 같은 타입만 허용. NULL 허용하지 않음.
- Type? : Type OR NULL
// 코틀린 타입은 기본적으로는 널(NULL) 을 허용하지 않는다.
fun strLenNonNull(str: String): Int {
// 파라미터로 받은 str 은 널이 될수 없으므로 안전하다.
return str.length
}
// 만일 널(NULL) 가능성이 있다면 타입에 ?를 붙여야 한다.
fun strLenNullable(str: String?): Int {
// 널 가능성이 있는 str 메소드에 접근하면 에러가 발생한다.
//return str.length
if( str != null ) {
// 널체크 이후 str 은 String? 타입에서 String 타입으로 스마트 캐스팅된다.
return str.length
}else{
return 0
}
}
- 안전한 호출 연산자 ?.
- 엘비스 연산자 ?:
// 문자열에 끝 Char 를 반환한다
fun strLastCharNullable(str: String?): Char? {
// ?. 연산자는 str 이 NULL 이면 null 이 반환된다.
return str?.get(str.length - 1)
}
// 문자열에 끝 Char 를 반환한다
fun strLastCharNullable(str: String?): Char {
// ?. 연산자는 str 이 NULL 이면 "".single() 이 반환된다.
return str?.get(str.length - 1) ?: "".single()
}
- 코틀린은 수신 객체가 널이 아닌 경우에만 실행되는 let 함수
// let 함수를 이용한 예제
fun strPrintLen(str: String?) {
// let 함수는 수신객체인 str 이 널이면 실행되지 않는다.
str?.let { print(strLenNonNull(it)) }
}
- as?
- as : 타입 캐스팅 연산자
class Test(val id: Int) {
// equals 를 오버라이드 함, id 가 같으면 같은 객체로 취급
override fun equals(other: Any?): Boolean {
// as? 연산자를 사용하면 타입이 같은 경우 캐스팅이 정상적으로 되고
// 캐스팅이 실패하면 null 이 반환된다.
// null 이 반환된 경우 엘비스 연산자의 디폴트 식이 실행되어 false 가 리턴된다.
val otherTest = other as? Test ?: return false
// otherTest 은 스마트캐스팅 되어 널을 신경쓸 필요가 없다.
return Test.id == id
}
}
* 널(Null)은 Java 에서 객체가 할당되지 않은 상태 를 의미한다.
* NPE( Null Pointer Exception ) 는 Java 에서 객체가 널 상태여서 발생하는 예외를 의미한다.
* Java 의 레퍼런스 타입은 널을 할당할 수 있지만, 널은 해당 타입의 메소드를 실행할 수 없으며 완전히 다른 타입이다.
* Java 에서 NPE 가 자주 발생하는 이유는 Java 의 레퍼런스 타입은 모두 널일 수 있지만 전부 널 체크를 하기 위해서는 코드가 복잡해지기 때문이다.
* 코틀린은 타입 시스템 자체에서 널 가능성을 체크한다.
* 코틀린의 Type 은 기본적으로 널을 할당할 수 없으며, 널 가능성이 있다면 Type?로 선언해야 한다.
* 코틀린은 널을 처리하기 위하여 여러 편리한 연산자를 제공한다.
'IT > Android(비공개)' 카테고리의 다른 글
[Android] View / Theme (0) | 2020.03.05 |
---|---|
Activity / Intent (0) | 2020.03.04 |
Android-studio / svn 연결 (0) | 2020.03.04 |
3. Kotlin(코틀린)_2 (0) | 2020.02.26 |
2. Kotlin(코틀린)_1 (0) | 2020.02.20 |
1. Android 기본 (0) | 2020.02.07 |
Android 재시작 (0) | 2020.02.07 |