Plus
Kotlin
에서는 연산자 오버로딩을 통해 연산자의 동작을 커스터마이징 할 수 있다.Plus
메서드를 오버로딩하면, +
연산자를 사용할 때, plus
메서드가 호출된다.
class MyNumber(val value: Int) {
operator fun plus(other: MyNumber): MyNumber {
return MyNumber(value + other.value)
}
}
fun main() {
val num1 = MyNumber(10)
val num2 = MyNumber(20)
val result = num1 + num2 // MyNumber의 plus 메서드가 호출됨
println(result.value) // 30 출력
}
위의 예시 코드를 보면 plus
를 오버로딩하기 위해서는 plus
앞에 operator
키워드를 꼭 붙여주어야 한다.
실수로 안썼는데, 호출하면 오류가 발생한다.
다른 여러가지 이항 산술 연산자
Plus
를 제외하고, 오버로딩 가능한 이항 산술 연산자는 더 존재한다.
a * b
- 사용방법 :
times
- 사용방법 :
a / b
- 사용방법 :
div
- 사용방법 :
a % b
- 사용방법 :
mod
- 사용방법 :
a + b
- 사용방법 :
plus
- 사용방법 :
a - b
- 사용방법:
minus
- 사용방법:
복합 대입 연산자
+
에 대해는 설명했으니, +=
의 경우에 대해 설명해보겠다.
예를 들어 a+=b
는 a = a + b
와 같다.plus
를 사용해도 되지만, 새로운 참조가 아닌 기존 객체의 내부의 값만 바꾸고 싶은 경우에는 복합 대입 연산자를 사용하면 된다.
이러한 복합 대입 연산자를 구현하기 위해서는 plusAssign
을 사용하면 된다. 사용방법은 기존 방법과 동일하다.
class MyNumber(var value: Int) {
operator fun plusAssign(other: MyNumber) {
this.value += other.value
}
}
fun main() {
val num1 = MyNumber(10)
val num2 = MyNumber(20)
num1 += num2 // MyNumber의 plusAssign 메서드가 호출됨
println(num1.value) // 30 출력
}
그런데, 주의할 점이 있다. 만약 plus
만 정의하고 plusAssign
을 정의하지 않았을 경우에는 plus
가 실행된다. 반면 plus
를 정의하지 않고 plusAssign
만 정의한다면, +
실행시 오류가 발생한다.
단항 연산자 오버로딩
단항 연산자를 오버로딩하기 위해 사용하는 함수는 인자를 취하지 않는다.
오버로딩할 수 있는 단항 산술 연산자
![![Action Koltin/#^Table1]]
비교 연산자 오버로딩
비교 연산도 가능하다.
equals
동등성 연산자인 equals
의 경우에는 override
키워드가 필요하다.
그 이유는 Any
에 정의된 메서드이므로, override
가 필요하다.
compareTo
정렬을 할 때 주로 많이 쓰는 Comparable 인터페이스에 있는 메서드 compareTo
는 한 객체와 다른 객체를 비교해 정수로 나타내준다.
컬렉션과 범위에 대해 쓸 수 있는 관례
컬렉션을 다룰 때 index
를 통해 원소를 읽거나 연산을 통해 어떤 값이 속하는지 검산하는 경우가 있다.
컬렉션과 관련한 관례를 설명해보겠다.
get / set : 인덱스로 원소에 접근
배열 원소에 접근할 때 어떻게 하는가? []
각괄호를 이용하여 접근해야 한다는 사실은 알고 있을 것이다.
원소에 접근하여 읽는 것은 get
을 이용한 접근이다.
값에 대해 쓰는 방법은 set
을 이용하는 방법이다.
두 방법 다, operator
키워드를 이용하여 구현할 수 있다.
in
in
은 객체가 컬랙션에 있는지 검사한다.in
은 contains
와 대응된다.
예들들어 왼쪽 위 좌표와 오른쪽 아래 좌표가 주어졌을 때 좌표 값이 사각형 안에 들어가는지 확인하는 방법은 다음과 같다.
data class Rectangle(val ul : Point, val lr : Point)
operator fun Rectangle.contains(p : Point) : Boolean {
return p.x in ul.x until lr.x && p.y in ul until lr.y
}
containts
를 다음과 같이 작성하여, 가로와 세로 범위 안에 드는지 확인하면 된다.
rangeTo
방금 in
을 설명하면서 작성한 코드에서 until
의 경우에는 범위을 만드는 구문이다.
..
도 범위를 만드는 구문이다. rangeTo
는 아무 클래스나 만들 수 없다. Comparable
인터페이스가 구현하면 rangeTo
를 구현할 필요가 없다.
구조 분해 선언과 component 함수
kotlin
에서는 구조 분해 선언 특성이 있다.
구조 분해 선언이란?
복합적인 값을 분해해서 여러 다른 변수를 한번에 초기화 하는 것이다.
예를 들어 Point
클래스로 저장된 값을 x
y
에 저장하고 싶다면,
val p = Point(10,20)
val (x,y) = p
다음과 같이 작성할 수 있다.
Point
는 각각 component1()
과 component2()
함수를 통해 구조분해 된다.
여기서 중요한 점은 그렇다면, 무한히 componentN()
을 만들 수 있는거 아닌가? 라는 생각이 들 수 있다.
만드는 것은 가능하다, 하지만 가독성
과 유지보수
면에서 코드를 해칠 수 있다. 만약 그래도 쓰고 싶다면, 원하는 만큼 정의하면 된다.
구조 분해 선언과 루프
루프문 내부에서도 당연히 구조 분해 선언을 사용할 수 있다.Map
형태로 이루어진 데이터를 루프를 돈다고 한다면
for ((key, value) in map){
}
다음과 같이 작성할 수 있다.
위임 프로퍼티
위임 프로퍼티는 무엇인가?
프로퍼티의 getter
, setter
를 다른 객체에 위임하여 간편하게 프로퍼티의 동작을 정의할 수 있게 해주는 기능이다.
Lazy 위임
lazy
는 프로퍼티 값을 처음 접근할 때 초기화하는 방법을 제공한다.lazy
를 통해 처음 사용할 때 까지 초기화를 미룰 수 있는 방법이다.
val lazyValue: String by lazy {
println("initialized") "Hello"
}
fun main() {
println(lazyValue) // "initialized"와 "Hello"를 출력
println(lazyValue) // "Hello"만 출력
}
다음 코드가 있을 때, 처음 실행했을 때 lazy
의 값이 초기화 되므로, initialized
와 Hello
가 출력이 된다.
하지만 두번째 출력 이후부터는 이미 초기화 되었으므로 Hello
만 출력된다.
사용자 직접 정의
사용자가 직접 delegate
를 작성하여 사용할 수도 있다.
class Delegate {
operator fun getValue() {}
operator fun setValue() {}
}
class Foo {
var p : Type by Delegate()
}
Observable 위임
Delegates.observable()
함수를 사용하면 프로퍼티의 변경을 감지할 수 있다. 프로퍼티가 변경될 때마다 콜백 함수가 호출된다.
import kotlin.properties.Delegates
var name: String by Delegates.observable("<no name>") { prop, old, new ->
println("$old -> $new")
}
fun main() {
name = "first" // "<no name> -> first"를 출력
name = "second" // "first -> second"를 출력
}
여기서 prop
은 프로퍼티이다. 만약 프로퍼티의 이름을 알고 싶다면, prop.name
을 통해 접근하면 된다.
'안드로이드 > Action Kotlin' 카테고리의 다른 글
Action Kotlin 5 - 코틀린 타입 시스템 (0) | 2023.10.27 |
---|---|
Action Kotlin 4 - 람다로 프로그래밍 (0) | 2023.10.25 |
Action Kotlin 3 - 클래스, 객체, 인터페이스 (1) | 2023.10.24 |
Action Kotlin 2 - 함수의 정의와 호출 (0) | 2023.10.24 |
Action Kotlin - 1 (0) | 2023.10.24 |