코틀린 기능
컬렉션
시퀀스
영역 함수
코틀린 대리자
컬렉션
배열 다루기
arrayOf 함수를 이용해 배열을 만들고
Array 클래스에 들어 있는 속성과 메소드를 이용해 배열에 들어 있는 값을 다룰 수 있다.
코틀린은 배열을 생성하는 arrayOf 라는 이름의 간단한 팩토리 메소드를 제공
val string = arrayOf("this", "is", "an", "array", "of", "strings")arrayOfNulls 팩토리 메소드를 사용해 널로만 채워진 배열을 생성 가능
val nullStringArray = arrayOfNulls<String>(5)Array 클래스에는 public 생성자가 하나만 존재하고, 이 생성자는 아래 두 인자를 받는다.
Int 타입의 size
init, 즉 (Int) -> T 타입의 람다
val squares = Array(5) { i -> (i * i).toString() }.
코틀린에는 오토박싱, 언박싱 비용을 방지할 수 있는 기본 타입을 나타내는 클래스가 있다.
booleanArrayOf
byteArrayOf
shortArrayOf
charArrayOf
intArrayOf
longArrayOf
floatArrayOf
ShortArray
배열의 확장 메소드
👉🏻 배열의 적법한 인덱스 값 획득하기
.
일반적으로 배열을 순회할 때 표준 for-in 루프를 사용하지만 배열의 인덱스 값도 같이 사용하고 싶다면, withIndex 함수를 사용하자
👉🏻 withindex를 사용해 배열 값이 접근하기
컬렉션 생성하기
List, Set, Map은
listOf, setOf, mapOf 처럼 변경 불가능한 컬렉션을 생성하기 위해 만들어진 함수나
mutableListOf, mutableSetOf, mutableMapOf 처럼 변경 가능한 컬렉션을 생성하기 위해 고안된 함수 중 하나를 사용
👉🏻 불변 List, Set, Map 생성하기
기본적으로 코틀린 컬렉션은 불변이다.
컬렉션은 원소를 추가하거나 제거하는 메소드를 지원하지 않는다.
컬렉션을 변경하는 메소드는 팩토리 메소드에서 제공하는 가변 인터페이스에 들어 있다.
mutableListOf
mutableSetOf
mutableMapOf
👉🏻 가변 List, Set, Map 생성하기
👉🏻 List, Set, Map 인터페이스를 직접 구현한 클래스의 인스턴스 생성
컬렉션에서 읽기 전용 뷰 생성하기
toList, toSet, toMap 메소드를 사용해 새로운 읽기 전용 컬렉션을 생헝하자
👉🏻 List 타입의 레퍼런스를 리턴하는 toList 메소드 호출
👉🏻 독립된 객체를 생성하는데 독립된 객체의 내용은 원본과 같지만 더 이상 같은 객체를 나타내지는 않는다.
👉🏻 내용이 같은 읽기 전용 뷰를 생성하고 싶다면, List 타입의 레퍼런스에 가변 리스트를 할당하자.
컬렉션에서 맵 만들기
키 리스트가 있을 때 각각의 키와 생성한 값을 연관시켜 맵을 만들려면
associateWith함수에 각 키에 대해 실행되는 람다를 제공해 사용하자.
👉🏻 associateWith로 값 생성하기
컬렉션이 빈 경우 기본값 리턴하기
컬렉션이나 문자열이 비어 있는 경우 ifEmpty, ifBlank 함수를 사용해 기본값을 리턴하자.
👉🏻 기본값 테스트
주어진 범위로 값 제한하기
값이 주어졌을 때, 주어진 값이 특정 번위 안에 들면 해당 값을 리턴하고,
그렇지 않다면 범위의 최솟값 또는 최댓값을 리턴하려면
kotlin.ranges의
coerceIn함수를 범위 인자 또는 구체적인 최솟값, 최댓값과 함께 사용하자.
👉🏻 coerceIn 함수는 값이 범위 안에 있으면 해당 값을 리턴하고 그렇지 않다면 범위의 경계 값을 리턴
👉🏻 원하는 최대/최솟값이 있다면 범위를 생성하지 않아도 된다.
리스트 구조 분해하기
최대 5개의 원소를 가진 그룹에 리스트를 할당하기
👉🏻 리스트의 원소를 구조 분해하기
코틀린 표준 라이브러리의 List 클래스에 N이 1부터 5까지인 componentN 이라는 확장 함수가 정의되어 가능한 동작
데이터 클래스는 정의된 모든 속성 관련 component 메소드를 자동으로 추가
데이터 클래스가 아닌 클래스를 정의하면 필요한 component 메소드를 직접 정의 가능
다수의 속성으로 정렬하기
sortedWith,comparedBy함수로 다수 속성으로 정렬을 해보자.
👉🏻 연이은 속성으로 골프 선수 정렬하기
compareBy함수는 Comparator 를 생성하고,Comparator 속성을 추출하는 선택자 목록을 제공
차례차례 정렬에 사용되는 Comparator 생성
sortedWith함수는 Comparator 를 인자로 받는다.
👉🏻 비교 후 새로운 비교를 적용하는 thenBy 함수
위 테스트와 동일한 결과를 보임
사용자 정의 이터레이터 정의하기
next, hasNext 함수를 모두 구현한 iterator 를 리턴하는 연산자 함수 정의하기
kotlin.collections Iterator Interface
👉🏻 확장 함수로 iterator 정의하기
👉🏻 iterator 구현
타입으로 컬렉션을 필터링하기
filterIsInstanceorfilterIsInstanceTo확장 함수로여러 타입이 섞여 있는 컬렉션에서 특정 타입의 원소로만 구성된 새 컬렉션을 생성할 수 있다.
코틀린 컬렉션은 특정 불리언 조건을 만족하는 원소를 필터링하기 위해 사용되는 Predicate를 인자로 받는 filter 확장 함수를 포함한다.
👉🏻 위와 같은 상황에서 filterIsInstance 함수를 사용
filterIsInstance 함순은 구체적인 타입을 사용
범위를 수열로 만들기
정수 또는 문자로 구성되어 있지 않는 수열의 범위를 순회하려면 사용자 정의 수열을 생성하자.
사용자 정의 수열은 IntProgression, LongProgression, CharProgression 처럼 Iterable 인터페이스를 구현해야 한다.
👉🏻 LocalDate Progression
👉🏻 LocalData 수열 테스트
시퀀스
지연 시퀀스 사용하기
특정 조건을 만족시키는 데 필요한 최소량의 데이터만 처리하고 싶다면
코틀린 시퀀스를
쇼트 서킷 함수와 함께 사용하자
쇼트 서킷: 특정 조건에 다다를 때까지 오직 필요한 데이터만을 처리하는 방식
👉🏻 filter 함수 사용하기
👉🏻 시퀀스 사용하기
시퀀스가 비었다면 first 함수는 예외를 던지므로 firstOrNull을 사용하자
시퀀스 생성하기
이미 원소가 있다면
sequenceOfIterable이 있다면
asSequence그외의 경우는 시퀀스 생성기를 사용핵서
시퀀스를 생성하자
👉🏻 원소나, Iterable이 존재하는 경우 시퀀스 생성
generateSequence
👉🏻 무한의 원소를 갖는 시퀀스 생성하기
다음 소수를 찾기 위해 얼마나 많은 수를 확인해야 하는지 알 수 없는 이러한 경우 시퀀스를 사용하기 좋은 이유
무한 시퀀스 다루기
무한대의 원소를 갖는 시퀀스의 일부분이 필요하다면,
널을 리턴하는 시퀀스 생성기를 사용하거나, 시퀀스 확장 함수 중 takeWhile 같은 함수를 사용하자.
시퀀스에서 yield하기
구간을 지정해 시퀀스에서 값을 생성하려면
yield 중단 함수와 함께 sequence 함수를 사용하자
sequence 함수는 주어진 블록에서 평가되는 시퀀스를 생성
이 블록은 인자 없는 람다 함수이며 void를 리턴하고 평가 후 SequenceScope 타입을 받는다.
SequenceScope
yield 함수는 이터레이터에 값을 제공하고 다음 값을 요청할 때까지 값 생성을 중단
👉🏻 시퀀스 연산에서 값 추출하기
yield는 중단 함수이고 코루틴과도 잘 동작
코루틴에 값을 제공한 후 다음 값을 요청할 때까지 해당 코루틴을 중단시킬 수 있다.
영역 함수
let, run, apply, also
apply로 객체 생성 후 초기화
객체 사용 전 생성자 인자만으로 할 수 없는 초기화 작업이 필요할 경우 apply 함수를 사용하자.
apply 함수는 this를 인자로 전달하고 this를 리턴하는 확장 함수다.
모든 제네릭 타입
T에 존재하는 확장 함수명시된 블록을 수신자인
this와함께 호출하고 해당 블록이 완료되면this리턴
👉🏻 apply를 사용하여 단 하나의 구문으로, 저장해야 할 인스턴스를 받아 새로운 키로 한번에 갱신
apply 블록은 이미 인스턴스화된 객체의 추가 설정을 위해 사용하는 가장 일반적인 방법
부수 효과를 위한 also
부수 효과를 생성하는 동작을 수행하려면
also함수를 사용하자.
also 함수는 코틀린 표준 라이브러리에 있는 확장 함수
모든 제네릭 타입 T에 추가되고
block 인자 호출 수 자기 자신을 리턴
👉🏻 also는 일반적으로 객체에 함수 호출을 연쇄시키기 위해 사용
👉🏻 서비스 테스트 작성 시 부수 효과로 로그 기록
let 함수와 엘비스 연산자
레퍼런스가 널일경우 기본값을 리턴하도록 하려면
엘비스 연산자를 결합한 안전 호출 연산자와 함께 let 영역 함수를 사용하자.
let 함수는 모든 제네릭 타입 T의 확장 함수
컨텍스트 객체가 아닌 블록의 결과를 리턴
객체를 위한 map처럼 마치 컨텍스트 객체의 변형처럼 동작
👉🏻 문자열 대문자 변경과 특수한 입력 처리
임시 변수로 let
연산 결과를 임시 변수에 할당하지 않고 처리하고 싶다면,
연산에 let 호출을 연쇄하고 let에 제공된 람다 또는 함수 레퍼런스 안에서 그 결과를 처리하자
👉🏻 임시 변수를 사용하지 않고 let 함수로 바로 처리
👉🏻 List 출력을 위해 let(or also) 사용
let함수는 블록의 결과를 리턴also함수는 컨텍스트 객체를 리턴출력과 같은 부수적인 효과는 also를 사용하는 것이 더 코틀린다운 사용법
코틀린 대리자
대리자를 사용해서 합성 구현하기
연산을 위임할 메소드가 포함된 인터페이스를 만들고.
클래스에서 해당 인터페이스를 구현한 후
by키워드를 사용해 바깥쪽에 래퍼 클래스를 만들자
코틀린에서 by 키워드는 포함된 객체에 있는 모든 public 함수를 이 객체를 담고 있는 컨테이너를 통해 노출할 수 있다.
컨테이너에 노출하려면 포함된 객체의 public 메소드의 인터페이스를 생성해야 한다.
생성자에서 객체를 인스턴스화하고 모든 public 함수를 위임하도록 정의할 수 있다.
오직 포함된 객체의 public 함수만 노출
lazy 대리자 사용하기
어떤 속성이 필요할 때까지 해당 속성의 초기화를 지연시키고 싶다면
lazy대리자를 사용하자
코틀린은 어떤 속성의 획득자와 설정자가 대리자라고 불리는 다른 객체에서 구현되어 있다는 것을 암시하기 위해 속성에 by 키워드를 사용
코틀린 표준 라이브러리에 다수의 대리자 함수가 있는데,
그 중 가장 인기 있는 함수는
lazy
👉🏻 처음 접근까지 속성의 초기화를 대기
첫 호출은 lazy가 받은 람다를 실행하고 그 다음 변수에 저장될 값을 리턴
내부적으로 이 값을 캐시하는 Lazy 타입의
ultimateAnswer$delegate라는 특별한 속성을 생성
lazy는 LazyThreadSafetyMode 타입의 이넘도 인자로 받는다.
SYNCHRONIZED
오직 하나의 스레드만 Lazy 인스턴스를 초기화할 수 있게 락 사용
PUBLICATION
초기화 함수가 여러 번 호출될 수 있지만 첫 번째 리턴값만 사용
NONE
락이 사용되지 않음
값이 널이 될 수 없게 만들기
notNull 함수를 이용해 값이 설정되지 않았다면 예외를 던지는 대리자를 제공하자.
속성 초기화를 지연시키는 한 가지 방법은 속성에 처음 접근하기 전에 속성이 사용되면 예외를 던지는 대리자를 제공하는 notNull 함수를 사용하는 것이다.
👉🏻 속성에 값이 제공되기 전 접근을 시도하면 IllegalStateException
observable, vetoable 대리자
변경 감지에는
observable함수를변경 적용 여부를 결정할 때는
vetoable함수와 람다를 사용하자.
대리자로서 Map 제공
맵을 제공해 객체를 초기화하고 싶을 경우 getValue, setValue 함수 구현을 사용하자.
👉🏻 MutableMap을 인자로 받고 해당 맵의 키에 해당하는 값으로 클래스 속성 초기화
👉🏻 JSON 문자열로 속성을 파싱할 경우에도 사용
사용자 정의 대리자 만들기
ReaOnlyPropertyorReadWriteProperty를 구현하는 클래스를 생성하여 직접 속성 대리자를 작성하자.
값을 획득하거나 설정하는 동작을 다른 객체에 위임할 수 있다.
사용자 정의 속성 대리자를 생성하려면
ReaOnlyPropertyorReadWriteProperty인터페이스에 존재하는 함수를 제공해야 한다.
ReaOnlyProperty, ReadWriteProperty 인터페이스의 시그니처
대리자를 만들려고 위 인터페이스를 구현할 필요가 없다.
아래 코드에 보이는 시그니처와 동일한 getValue, setValue 함수만으로 충분하다.
👉🏻 간단한 대리자 예제
완전히 다른 예제 집합으로 그레이들 빌드 도구는 위임된 속성을 통해 컨테이너와 상호작용할 수 있게 도와주는 Kotlin DSL을 제공한다.
프로젝트 자체(org.gradle.api.Project)와 연관된 속성의 집합
프로젝트 전체에 사용할 수 있는 extra 속성
Last updated