연산자 오버로딩 전에
연산자 오버로딩을 알아보기전에 연산자가 작동하는 시스템에 대해 알아볼 필요가 있다.
모든 연산자는 매소드를 통해서 작동한다.
3 + 4 라는 연산을 한다고 하자.
하지만 프로그래밍상에는 3.plus(4) 라는 매소드가 작동하는 것이다.
그렇기에 연산자는 모두 매소드 형태로 작동됨을 인지해야 연산자 오버로딩을 이해하는데 편리하다.
산술 연산자
class Print(var usedPage: Int, var ink: Double) {
operator fun plus(p: Print): Print {
return Print(this.usedPage + p.usedPage, this.ink + p.ink)
}
override fun toString(): String {
return "usedPage : " + this.usedPage + " | Ink : " + this.ink
}
}
fun main() {
var printer1 = Print(0, 50.0)
var printer2 = Print(0, 50.0)
printer1.usedPage++
printer2.usedPage += 2
val total = printer1 + printer2
println(total.toString())
}
위의 코드블럭 블럭을 보면 18번째 코드를 보면 클래스간의 덧셈을 볼 수 있다.
이처럼 클래스 간의 덧셈을 도와주는 것이 연산자 오버로딩이다.
쉽게 생각해서 연산자를 override 한다고 생각하면 쉽다.
2 ~ 4 번째 코드가 연산자 오버로딩한 것이다. operator fun [연산자] 하는 형식을 띈다.
우리가 가장 먼저 떠오르는 산술 연산자 오버로딩은 다음과 같다.
-
plus +
-
minus -
-
times *
-
div /
-
rem %
-
rangeTo ..
15번째 코드줄도 printer1++ 형식으로 오버로딩 할 수 있다.
산술 연산자를 오버로딩하면 대입연산자도 자동적으로 오버로딩이 되어진다.
-
plusAssign +=
-
minusAssign -=
-
timesAssign *=
-
divAssign /=
-
remAssign %=
하지만 여기서 유의해야 할 점은 plus 매소드의 파라미터는 Print 클래스로 되어져 있다.
매소드는 파라미터가 다르면 다른 매소드로 인식하기에 그렇기에 16번째 코드 += 대입연산자는 오버로딩이 안된 상태이다.
Int 형을 파라미터로 갖는 매소드를 추가해주어야 한다. 그러므로
operator fun plus(n: Int): Print {
return Print(this.usedPage + n, ink)
}
혹은
operator fun plus(p: Any): Print {
when (p) {
is Print -> return Print(this.usedPage + p.usedPage, this.ink + p.ink)
is Int -> return Print(this.usedPage + p, ink)
}
return this
}
방식을 코드에 더해줘야 한다.
접두사 / 접미사 연산자
class Print(var usedPage: Int, var ink: Double) {
operator fun plus(p: Print): Print {
return Print(this.usedPage + p.usedPage, this.ink + p.ink)
}
operator fun inc(): Print = Print(this.usedPage++, ink)
override fun toString(): String {
return "usedPage : " + this.usedPage + " | Ink : " + this.ink
}
}
fun main() {
var printer1 = Print(0, 50.0)
val printer2 = Print(0, 50.0)
printer1++
printer2.usedPage += 2
val total = printer1 + printer2
println(total.toString())
}
-
inc ++
-
dec --
호출 연산자
호출 연산자는 가볍게 생각해서 ( ) 괄호를 생각하면 된다. 호출 연산자는 함수 호출을 돕는데 사용된다.
class Example {
operator fun invoke(msg:String){
println(msg)
}
}
fun main() {
val exam = Example()
exam.invoke("MSG")
exam("STRING")
}
/*
MSG
STRING
*/
다음과 같이 프러퍼티(파라미터) 를 했을 때 작동하고 싶은 것들을 오버로딩 할 수 있다.
인덱스 접근 연산자
인덱스 접근 연산자는 배열의 게터/세터를 다룰 때 사용 한다.
a[4] -> a.get(4) 와 같은 의미이다.
또한
a[4] = 5 -> a.set(4, b) 와 같은 의미이다.
단일 연산자
표현식 | 의미 |
+a | a.unaryPlus() |
-a | a.unaryMinus() |
!a | a.not() |
범위 연산자
표현식 | 의미 |
a in b | b.contains(a) |
a !in b | !b.contains(a) |
동등성 연산자
표현식 | 의미 |
a == b | a?.equals(b) ? : (b == null) |
a != b | !(a?.equals(b)) ? : (b == null) |
비교 연산자
표현식 | 의미 |
a > b | a.compareTo(b) > 0 |
a < b | a.compareTo(b) < 0 |
'Programming > Kotlin' 카테고리의 다른 글
[Kotlin/코틀린] 입력과 출력 (0) | 2020.10.03 |
---|---|
[Kotlin] 제네릭 / Generic (0) | 2020.03.19 |
[Kotlin] 내부 클래스(2) (0) | 2020.03.18 |
[Kotlin] 내부 클래스(1) (0) | 2020.03.15 |
[Kotlin] 데이터 클래스 (0) | 2020.03.15 |