일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 안드로이드 라이선스
- ar vr 차이
- 큐 자바 코드
- android ar 개발
- 플러터 설치 2022
- rxjava hot observable
- jvm 작동 원리
- rxjava cold observable
- 클래스
- 서비스 쓰레드 차이
- 스택 자바 코드
- ANR이란
- Rxjava Observable
- jvm이란
- 안드로이드 레트로핏 crud
- 안드로이드 라이선스 종류
- 객체
- 자바 다형성
- 서비스 vs 쓰레드
- rxjava disposable
- 안드로이드 유닛 테스트 예시
- 2022 플러터 설치
- 멤버변수
- 2022 플러터 안드로이드 스튜디오
- 안드로이드 유닛 테스트
- 안드로이드 유닛테스트란
- 안드로이드 레트로핏 사용법
- android retrofit login
- 안드로이드 os 구조
- 스택 큐 차이
- Today
- Total
나만을 위한 블로그
[이펙티브 코틀린] 아이템 22. 일반적인 알고리즘 구현 시 제네릭을 써라 본문
아규먼트로 함수에 값을 전달할 수 있는 것처럼 타입 아규먼트를 사용하면 함수에 타입을 전달할 수 있다.
타입 아규먼트를 사용하는 함수(즉 타입 파라미터를 갖는 함수)를 제네릭 함수라고 부른다. 대표적인 예로는 stdlib의 filter()가 있다. filter()는 타입 파라미터 T를 갖는다.
inline fun <T> Iterable<T>.filter(
predicate: (T) -> Boolean
): List<T> {
val destination = ArrayList<T>()
for (element in this) {
if (predicate(element)) {
destination.add(element)
}
}
return destination
}
filter()의 람다 표현식 내부에서 컴파일러가 아규먼트가 컬렉션의 요소와 같은 타입이라는 걸 알 수 있으므로 잘못 처리하는 걸 막을 수 있다. IDE도 이를 기반으로 여러 유용한 제안을 해 준다.
제네릭은 기본적으로 List<String> 또는 Set<User>처럼 구체적인 타입으로 컬렉션을 만들 수 있게 클래스, 인터페이스에 도입된 기능이다. 컴파일 과정에서 최종적으로 이런 타입 정보는 사라지지만 개발 중에는 특정 타입을 사용하게 강제할 수 있다. 이런 타입 정보 덕분에 MutableList<Int>에 안전하게 Int를 추가할 수 있다.
또한 Set<User>에서 요소를 꺼내면 그것이 User라는 걸 알 수 있다. 이런 기능은 정적 타입 프로그래밍 언어에선 굉장히 유용하게 활용된다.
코틀린은 강력한 제네릭 기능을 갖고 있지만 조금 복잡해서 이해하기 어렵다. 필자의 경험에 의하면 많은 코틀린 개발자가 variance 한정자를 어떤 형태로 사용하는지 잘 몰랐다.
제네릭 제한
타입 파라미터의 중요한 기능 중 하나는 구체적인 타입의 서브타입만 사용하게 타입을 제한하는 것이다. 아래 코드는 콜론 뒤에 슈퍼타입을 설정해 제한을 걸었다.
fun <T: Comparable<T>> Iterable<T>.sorted(): List<T> {
/* ... */
}
fun <T, C : MutableCollection<in T>>
Iterable<T>.toCollection(destination: C): C {
/* ... */
}
class ListAdapter<T: ItemAdapter> (/* ... */) { /*...*/ }
타입에 제한이 걸리므로 내부에서 해당 타입이 제공하는 메서드를 사용할 수 있다. 예를 들어 T를 Iterable<Int>의 서브타입으로 제한하면 T 타입을 기반으로 반복 처리가 가능하고 반복 처리 시 사용하는 객체가 Int라는 걸 알 수 있다. 또한 Comparable<T>로 제한하면 해당 타입을 비교할 수 있다는 걸 알 수 있다. 많이 사용하는 제한으로는 Any가 있다. 이는 nullable이 아닌 타입을 나타낸다.
inline fun <T, R: Any> Iterable<T>.mapNotNull(
transform: (T) -> R?
): List<R> {
return mapNotNullTo(ArrayList<R>(), transform)
}
'책 > Effective Kotlin' 카테고리의 다른 글
[이펙티브 코틀린] 아이템 24. 제네릭 타입과 variance 한정자를 활용하라 (0) | 2022.10.30 |
---|---|
[이펙티브 코틀린] 아이템 23. 타입 파라미터의 섀도잉을 피하라 (0) | 2022.09.13 |
[이펙티브 코틀린] 아이템 21. 일반적인 프로퍼티 패턴은 프로퍼티 위임으로 만들어라 (0) | 2022.09.11 |
[이펙티브 코틀린] 아이템 20. 일반적인 알고리즘을 반복해서 구현하지 마라 (0) | 2022.09.10 |
[이펙티브 코틀린] 아이템 19. knowledge를 반복해 사용하지 마라 (0) | 2022.08.30 |