티스토리 뷰
728x90
연산자 오버로딩
- - +, -, *, / 등 코틀린 내장 연산자에 대해 새로운 의미를 부여할 수 있게 해준다.
operator fun String.times(n: Int) = repeat(n)
fun main() {
println("abc" * 3) // abcabcabc
println("abc".times(3)) // abcabcabc
}
- 연산자를 구현하기 위해 함수 앞에 operator 키워드를 붙인다.
1. 단항 연산
enum class Color {
BLACK, WHITE, BLUE, YELLOW;
operator fun not() = when(this) {
BLACK -> WHITE
WHITE -> BLACK
BLUE -> YELLOW
YELLOW -> BLUE
}
}
fun main() {
println(!Color.BLUE) // YELLOW
}
식 | 의미 |
+e | e.unaryPlus() |
-e | e.unaryMinus() |
!e | e.not() |
2. 이항 연산
- 왼쪽 피연산자를 receiver, 오른쪽 피연산자를 인자로 받는다.
- 파라미터가 하나인 멤버/확장 함수여야 한다.
class A(val str: String, val i: Int) {
override fun toString() = "$str $i"
}
operator fun A.plus(other: A): A {
val ret = A(this.str + other.str, this.i + other.i)
return ret
}
fun main() {
println(A("Hello", 10) + A("World", 4)) // HelloWorld 14
}
식 | 의미 |
a + b | a.plus(b) |
a - b | a.minus(b) |
a .. b | a.rangeTo(b) |
a in b | b.contains(a) |
3. 중위 연산
public infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)
fun main() {
val pair1 = 1 to 2 // 중위 연산 사용
val pair2 = 1.to(2) // 일반적인 호출
}
- 중위 연산을 선언하기 위해 함수 앞에 infix를 붙여야 한다.
4. 복합 대입 연산
- 커스텀 복합 대입 함수가 있으면 그 함수를 사용하고, 없는 경우 이항 연산자와 대입 연산자로 해석한다.
- a += b 인 경우 plusAssign이 있으면 a.plusAssign(b), 없으면 a = a.plus(b)
- MutableList에 +=, -=를 사용하면 List에 원소가 추가되거나 삭제된다.
- 이는 대입 복합 연산인 plusAssign(), minusAssign()이 정의되어 있기 때문이다.
5. invoke(): 값을 함수처럼 사용
operator fun <K, V> Map<K, V>.invoke(key: K) = get(key)
fun main() {
val map = mapOf("I" to 1, "V" to 5, "X" to 10)
// invoke()를 통해 값을 함수처럼 사용
println(map("V")) // 5
println(map("L")) // null
}
- 함수 타입의 값은 자동으로 invoke()가 생성된다.
- 임의의 타입에 대해 invoke()를 생성할 수 있다.
class A private constructor() {
companion object {
fun make() = A()
}
}
operator fun A.Companion.invoke() = make()
fun main() {
val a = A() // invoke() -> make() -> private constructor
}
- invoke()를 통해 동반 객체를 팩토리로 만들 수 있다.
6. get(), set()
- List에서 []를 사용해 접근/변경 가능한 것도 operator fun get(), set()이 정의되어 있기 때문이다.
fun main() {
val list = mutableListOf(1, 2)
println(list[0]) // list.get(0)과 동일
list[1] = 3 // list.set(1, 3)과 동일
}
7. 구조 분해 (Destructuring)
class Person(val name: String, val age: Int) {
operator fun component1() = name
operator fun component2() = age
}
fun main() {
val (name, age) = Person("John", 20)
println("$name $age") // John 20
}
- 클래스의 멤버 함수나 확장 함수로 componentN을 정의하면 구조 분해를 사용할 수 있다.
- 구조 분해를 할 수 있는 data class, map, list, array에서도 componentN()이 정의되어 있다.
728x90
'kotlin' 카테고리의 다른 글
[kotlin/코틀린] 코루틴 기초 (suspend 함수, 코루틴 빌더, 문맥, 범위) (0) | 2023.07.19 |
---|---|
[kotlin/코틀린] 위임 프로퍼티 (0) | 2023.07.19 |
[kotlin/코틀린] 리플렉션 (0) | 2023.07.19 |
[kotlin/코틀린] 어노테이션 (0) | 2023.07.19 |
[kotlin/코틀린] 제네릭 (0) | 2023.07.19 |