Type Alias와 as import
Type Alias
긴 이름의 클래스 혹은 함수 타입이 있을 때 축약하거나 더 좋은 이름을 쓰고 싶은 경우 사용한다.
1
fun filterFruits(fruits: List<Fruit>, filter: (Fruit) -> Boolean) {}
- filter 라는 함수를 파라미터로 받고 있다.
- 이 파라미터는 Fruit를 파라미터로 받고 Boolean을 반환하는 함수이다.
- 그런데 너무 길다. 만약 파라미터가 추가된다면?
이런 경우 개선할 수 있다.
1
typealias FruitFilter = (Fruit) -> Boolean
- 타입을 마치 변수 선언하듯 선언해 사용할 수 있다.
- 위의 함수 파라미터에 typealias를 넣어주면 된다.
클래스도 비슷하다.
1
2
3
4
5
data class UltraSuperSuperGuardianTribe(
val name: String
)
typealias USGTMap = Map<String, UltraSupterSupterGuardianTribe>
as import
다른 패키지의 같은 이름 메서드를 동시에 가져오고 싶다면?
- as import : 어떤 클래스나 함수를 임포트할 때 이름을 바꾸는 기능
1
2
import com.~~.printHelloWorld as printHelloWordA
import com.~~.printHelloWorld as printHelloWordB
구조분해와 componentN 함수
- 구조분해
- 복합적인 값을 분해하여 여러 변수를 한 번에 초기화 하는 것.
1
2
val person = Person("Lee", 100)
val (name, age) = person // 구조 분해
- 여러 변수를 한 번에 초기화 할 수 있다.
- val name = “Lee”
- val age = 100
- Data Class는 componentN 이라는 함수도 자동으로 만들어준다.
- 위의 val (name, age) = person은 사실 아래와 같다.
- val name = person.component1()
- val age = person.componet2()
- componentN 이라는 메서드가 변수를 한 번에 초기화할 수 있도록 해주는 것이다.
- N이 순서이므로 만약 name과 age의 순서를 바꾸면 그것을 인식하는게 아니라 name에 age가 들어가고, age에 name이 들어가는 결과를 볼 수 있다.
데이터 클래스가 아닌 직접 선언하고 싶다면?
1
2
3
4
5
6
7
8
class Person(
val name: String,
val age: Int
) {
operator fun component1(): String {
return this.name
}
}
- 연산자의 속성을 가지고 있기 때문에 연산자 오버로딩을 하는 것처럼 간주돼야 한다.
- 따라서 operator 키워드를 붙여주어야 한다.
Jump와 Label
코틀린에서의 return, break, continue에 대해 알아보자.
- return
- 기본적으로 가장 가까운 enclosing function 또는 익명 함수로 값이 반환된다.
- break
- 가장 가까운 루프가 제거된다.
- continue
- 가장 가까운 루프를 다음 step으로 보낸다.
설명을 보면 Java와 다를게 없다.
for문 및 while문에서 break, continue 기능은 동일하다.
단, forEach에서 다르다.
1
2
3
4
5
6
fun main() {
val numbers = listOf(1, 2, 3)
numbers.map { number -> number + 1 }
.forEach { number ->
if (number == 3) continue (X)
println(number) }
- 일반적인 for문에서는 continue, break 등을 사용할 수 있다.
- 하지만 위와 같은 forEach에서는 continue, break 등을 사용하면 에러가 발생한다.
forEach문과 함께 break 또는 continue를 반드시 사용해야 한다면 아래와 같이 할 수 있다.
- break, continue를 사용할 때는 익숙한 for문을 사용하는 것도 방법이다.
Label
특정 Expression에 라벨이름@ 을 붙여 하나의 라벨로 간주하고 break, continue, return 등을 사용하는 기능
- 라벨을 사용하지 않았다면 가장 가까운 반복문인 j가 멈췄을 것이다.
- 라벨을 사용하여 바깥 반복문인 i 반복문을 멈출 수 있다.
- 하지만 사용을 추천하지 않는다.
- 위와 같이 해당 라벨이 있는 부분과 라벨을 이용한 break 등의 부분의 흐름이 계속 위아래로 움직일수록 복잡도가 증가해 예기치 않은 오류를 발생시킬 수 있다.
TakeIf와 TakeUnless
1
2
3
4
5
6
7
fun getNumberOrNull(): Int? {
return if (number <= 0) {
null
} else {
number
}
}
위와 같은 메서드를 method chaning을 위한 특이한 함수를 제공한다.
1
2
3
fun getNumberOrNullV2(): Int? {
return number.takeIf( it > 0 }
}
- 같은 의미의 코드이다.
- takeIf
- 주어진 조건을 만족하면 그 값이, 그렇지 않으면 null을 반환한다.
- takeUnless
- 주어진 조건을 만족하지 않으면 그 값이, 그렇지 않으면 null이 반환된다.