1. Type Alias와 as import
Type Alias
긴 이름의 클래스 또는 함수 타입이 있을때 별칭으로 사용할 수 있다.
typealias FruitFilter = (Fruit) -> Boolean // 별칭설정
private fun filterFruits(
fruits: List<Fruit>,
funcName: FruitFilter // 별칭으로 대체가능
): List<Fruit> {
return fruits
.filter(funcName)
}
data class suuuuuuuuuuuuuuuperdata(
val name:String
)
typealias superMap = Map<String,suuuuuuuuuuuuuuuperdata>
fun superMapOut(): superMap? {
return null
}
다른 패키지의 같은 이름인 함수를 동시에 가져오고싶다면
package lannstark.lec01
fun hello() {
println("hello lec01")
}
package lannstark.lec02
fun hello() {
println("hello lec02")
}
as import : 어떤 클래스나 함수를 임포트 할 때 이름을 바꾸는 기능
import lannstark.lec01.hello as helloFromLec01
import lannstark.lec02.hello as helloFromLec02
fun main() {
helloFromLec01()
helloFromLec02()
}
as 를 통해 각 함수의 이름을 다르게하여 가져온다.
as import 기능을 안쓴다면
package lannstark.lec03
import lannstark.lec02.hello
fun main() {
hello() // 먼저 import 해온 함수는 이름만으로 사용가능하다.
lannstark.lec01.hello() // 추후에 가져온 함수는 디렉토리 위치를 이용해야한다.
lannstark.lec02.hello() // 물론 먼저 가져온 함수도 디렉토리 위치를 이용해서 사용가능하다.
}
2. 구조분해와 componentN 함수
구조분해 : 복합적인 값을 분해하여 여러 변수를 한 번에 초기화하는 것
fun main() {
val person = Person("gil", 10)
val (name,age) = person // 구조분해는 로컬변수나 로컬값으로만 가능하다.
val person2 = Person2("gil", 10)
val (name2,age2) = person2
val name3= person.component1() // componentN 함수를 직접 사용할수도 있다.
val age3= person.component2()
}
data class Person(
val name:String,
val age:Int
)
//data class가 아닐때 구조분해를 사용하려면 componentN()를 수동 추가해줘야한다.
class Person2(
val name:String,
val age:Int
){
operator fun component1() = name
operator fun component2() = age
}
Data Class는 componentN 함수도 자동으로 만들어준다
Data Class가 아닌데 구조분해를 사용하고 싶다면, componentN 함수를 직접 구현해주면된다.
val map = mapOf(1 to "A",2 to "B")
for ((key, value) in map.entries) { // (key,value) 또한 구조분해이다. entry를 분해한것
}
val (age,name) = person // 받는 순서를 주의해야한다. 컴포넌트 순서대로 나오기 때문이다.
operator fun component1() = name
operator fun component2() = age
operator 지시어는 연산자 오버로딩(operator overloading)을 허용하기 위해 사용됩
operator를 이용하여 기본적으로 정의된 연산자를 오버로딩 할 수 있다.
(a,b) 같은 구조분해선언도 연산자이기때문에 operator를 붙여줘야한다.
+ 연산자 오버로딩 예시)
data class Vector(val x: Int, val y: Int) {
operator fun plus(other: Vector): Vector {
return Vector(x + other.x, y + other.y)
}
}
fun main() {
val v1 = Vector(3, 4)
val v2 = Vector(1, 2)
val result = v1 + v2 // operator fun plus 호출
println(result) // Vector(x=4, y=6)
}
Kotlin에서 람다식 안에서 매개변수를 ()로 감싸면 구조 분해(destructuring)로 인식
일반코드)
fun printPerson(person: Person?) {
person?.let{ p ->
println(p.name)
println(p.age)
}
}
구조분해 사용)
fun printPerson(person: Person?) {
person?.let{ (name,age) ->
println(name)
println(age)
}
}
3. Jump와 Label
- return : 기본적으로 가장 가까운 enclosing function[감싸져있는 함수] 또는 익명함수로 값이 반환된다
=> 가까운 함수가 종료되면서 값을 반환해준다는 뜻
- break : 가장 가까운 루프가 제거된다
- continue : 가장 가까운 루프를 다음 step으로 보낸다
코틀린에서 for문 및 while 문에서 break, continue 기능은 동일하다.
자바,코틀린 둘다 forEach에서 continue, break를 사용할 수 없다.
val numberList = listOf(1, 2, 3)
numberList.map { number -> number + 1 }
.forEach {
number ->
print(number+1)
println(number)
// break 사용할 수 없다.
// continue 사용할 수 없다.
}
List<Integer> numbers = List.of(1, 2, 3);
numbers.stream()
.forEach((number) ->{
if (number == 3) {
break; / /컴파일 에러
}
});
코틀린을 이용해서 forEach에서 continue, break를 사용하려면
run{
numberList.forEach {
number ->
if(number==3){
return@run // break 기능
}
if(number ==4){
return@forEach // continue 기능
}
print(number+1)
println(number)
}
}
run이라는 중괄호에서 다음과 같이 사용하면된다. -> 밑에서 설명할 Label 기능을 이용해서 구현된것이다.
run이라는 라벨을 return해서 foreach 전체를 끝내는 return기능을 구현한거고
foreach라는 라벨을 return해서 continue 기능을 구현한것이다.
[ 코틀린에서는 람다의 이름(혹은 함수 이름)을 암묵적으로 라벨로 사용할 수 있습니다.]
하지만 break, continue를 사용할 때엔 가급적 익숙한 for문 사용하자.
Label
코틀린에는 라벨이라는 기능이 있다
특정 expression에 라벨이름@ 을 붙여 하나의 라벨로 간주하고 break, continue, return 등을 사용하는 기능
abc@for (i in 1..100) {
for (j in 100 downTo 1 step 2) {
for (k in 50..500) {
if (j == 2) {
break@abc; // 라벨이 지정된 반복문을 탈출하게 된다.
}
}
}
}
라벨을 사용한 Jump는 사용하지 않는 것을 강력 추천한다.
4. TakeIf와 TakeUnless
Kotlin에서는 method chaning을 위한 특이한 함수를 제공한다.
takeIf
주어진 조건을 만족하면 그 값이, 그렇지 않으면 null이 반환된다
fun getNumeberOrNull(number: Int): Int? {
// return number.takeIf { it > 0 } 람다의 파라미터가 하나이고 컴파일러가 타입을 추론할 수 있는 경우 it 을 사용할 수 있다.
// return number.takeIf { number > 0 } number 람다 외부의 변수이고, 코틀린은 람다 외부변수를 받을 수 있다.
return number.takeIf { value -> value > 0 } // 일반적인 람다식
// 위의 3가지 다 정상동작한다.
}
위에서는 number가 0보다 크다면 number를 반환
아니라면 null을 반환해준다.
takeUnless
takeIf 와 반대로 동작한다.
주어진 조건을 만족하면 null , 그렇지 않으면 그 값이 반환된다.
return number.takeUnless { value -> value > 0 }
takeUnless를 사용했다면 value가 0보다 크다면 null 아니라면 number를 반환한다.
'인프런 > 자바 개발자를 위한 코틀린 입문' 카테고리의 다른 글
13) 코틀린의 scope function (0) | 2025.01.12 |
---|---|
11) 코틀린에서 컬렉션을 함수형으로 다루는 방법 (0) | 2025.01.10 |
10) 코틀린에서 람다를 다루는 방법 (0) | 2025.01.10 |
9) 코틀린에서 다양한 함수를 다루는 방법 (0) | 2025.01.10 |
8) 코틀린에서 배열과 컬렉션을 다루는 방법 (0) | 2025.01.09 |
댓글