231223 TIL #276 Kotlin #11 연산자 오버로딩

김춘복·2023년 12월 23일
0

TIL : Today I Learned

목록 보기
276/571

Today I Learned

Kotlin in Action 이어서 연산자 오버로딩!


연산자 오버로딩

  • 관례(Convention) : 어떤 언어 기능과 미리 정해진 이름의 함수를 연결해주는 기법

산술 연산자 오버로딩 operator

코틀린에서 관례를 사용하는 가장 대표적인 예.
자바에서는 원시타입과 String 타입만 + 연산자를 쓸 수 있다.
하지만 코틀린에선 좀 더 넓은 범위에서 오버로딩을 통해 사용할 수 있다.

이항 산술 연산 오버로딩

  • 연산자를 오버로딩하는 함수 앞에는 항상 operator를 붙여야 한다.

  • operator 변경자로 plus 함수를 선언하면 +로 plus를 할 수 있다.
    a+b -> a.plus(b)

  • 확장함수로도 오버로딩 구현이 가능하다.

data class Point(val x: Int, val y: Int) {
    operator fun plus(other: Point) : Point {
        return Point(x+other.x, y+other.y)
    }
}

fun main() {
    val p1 = Point(10,20)
    val p2 = Point(30,40)
    println(p1+p2)
}
  • 오버로딩 가능한 이항 산술 연산자
함수 이름
a * btimes
a / bdiv
a % bmod(1.1부터 rem)
a + bplus
a - bminus
  • 직접 정의한 함수로 구현해도 연산자 우선순위는 숫자 연산과 같다. (*,/,% > +,-)

  • 두 피연산자의 타입이 달라도 구현만 신경써서 해두면 상관없고, return 타입이 피연산자 타입과 달라도 괜찮다.


복합 대입 연산자 오버로딩

plus 같은 연산자를 오버로딩하면 + 뿐만아니라 관련 복합 대입 연산자인 +=도 함께 지원한다.

    var p3 = Point(100,200)
    p3 += Point(300,400)
    println(p3) // Point(x=400, y=600)
  • 코틀린 표준 라이브러리는 변경 가능한 컬렉션에 대해 plusAssign을 정의하며 아래와 같은 연산도 가능하다.
    val nums = ArrayList<Int>()
    nums += 42
    println(nums[0]) // 42
  • +와 -는 항상 새로운 컬렉션을 반환한다.
    +=, -= 연산자는 항상 변경가능한 컬렉션에 적용해 그 컬렉션을 변화시킨다.
    읽기 전용 컬렉션에서는 연산을 적용한 복사본을 반환한다.

단항 연산자 오버로딩

-a, b++ 같은 단항 연산자도 코틀린에선 오버로딩이 가능하다.

operator fun Point.unaryMinus() : Point {
    return Point(-x,-y)
}

// ...
    val p4 = Point(10,20)
    println(-p4) // Point(x=-10, y=-20)
  • 오버로딩 가능한 단항 산술 연산자
함수 이름
+aunaryPlus
-aunaryMinus
!anot
++a, a++inc
--a, a--dec
  • inc, dec는 전위, 후위 증감 모두 지원한다.

비교 연산자 오버로딩

동등성 연산자 equals

코틀린은 == 연산자 호출을 equals 메서드 호출로 컴파일한다. != 연산자도 자동으로 지원된다.
a==b를 처리할 때, a가 null인지 판단해서 널이 아닌경우에만 a.equals(b)를 호출한다.
a가 null이면 b도 null이여야 true다.

  • a == b -----> a?.equals(b) ?: (b==null)

순서 연산자 compareTo

자바에서 최대값, 최솟값, 정렬 등 비교를 해야하는 알고리즘에서는 Comparable 인터페이스를 구현한다. compareTo는 Comparable 인터페이스에 들어있고, 한 객체와 다른객체의 크기를 비교해 정수로 나타낸다.
코틀린도 똑같은 Comparable 인터페이스를 지원한다.

  • 비교연산자(>,<,<=,>=)는 compareTo 호출로 컴파일 된다. 반환값은 Int다.

  • a >= b -------> a.compareTo(b) >= 0

  • 아래는 Compareble을 구현해 compareTo를 오버라이드한 예시이다.
    compareValuesBy라는 코틀린 표준 라이브러리 함수를 사용했다.
    이 함수는 두 객체를 받아들이고 뒤에 비교할 속성을 나열하는 함수이다.

class Person(val firstName: String, val lastName: String) : Comparable<Person> {
    override fun compareTo(other: Person): Int {
        return compareValuesBy(this, other, Person::lastName, Person::firstName)
    }
    
    //...
    
    val person1 = Person("Kim", "KY")
    val person2 = Person("Ryu", "CB")
    println(person1 > person2) // true
}
profile
Backend Dev / Data Engineer

0개의 댓글