본문 바로가기

Dev Book/Kotlin IN ACTION

CH7(7.2). 비교 연산자 오버로딩

1. 동등성 연산자: equals

- 코틀린은 관례에 따라 == 연산자 호출을 equals 메소드 호출로 컴파일한다. != 연산자를 사용하는 식도 equals 호출로 컴파일된다. 이 연산자의 경우 내부에서 인자가 널인지 검사해서 널이 아닌 경우에만 equals를 호출한다.

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

 

class Point2(val x:Int, val y:Int){
    override fun equals(obj: Any?): Boolean{
        if(obj === this) return true //최적화: 파라미터가 this와 같은 객체인지
        if(obj !is Point) return false
        return obj.x==x && obj.y==y //Point로 스마트 캐스트 후 접근
    }
}

 

식별자 비교 연산자(===)를 사용해 equals의 파라미터가 수신 객체와 같은지 비교함으로써 최적화 한다. 다른 연산자 오버로딩 관례와 달리 equals는 Any에 정의된 메소드이므로 override가 필요하다. (동등성 비교를 모든 코틀린 객체에 적용) 상위 클래스에서 정의 된 메소드를 오버라이드하는 것이므로 앞에 따로 operator를 붙이지는 않아도 자동으로 상위 클래스의 operator 지정이 적용된다. 또한 Any에서 상속 받은 equals가 확장 함수보다 우선순위가 높기 때문에 equals를 확장함수로 정의할 수 없다.

2. 순서 연산자: compareTo

- 자바에서는 <나 > 등의 연산자로는 원시 타입의 값만 비교 가능했다. 그러나 코틀린은 Comparable 인터페이스 안에 있는 compareTo 메소드를 호출하는 관례를 제공한다. 따라서 비교 연산자는 compareTo 호출로 컴파일된다.

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

 

class Person(val firstName:String, val lastName:String): Comparable<Person>{
    override fun compareTo(other: Person): Int {
        return compareValuesBy(this, other, Person::lastName, Person::firstName)
    }
}

 

compareValuesBy 함수는 두 객체와 여러 비교 함수를 인자로 받는다. 첫번째 비교 함수에 두 객체를 넘겨서 두 객체가 같지 않다는 결과가 나오면 그 결과 값을 즉시 반환하고, 두 객체가 같다는 결과가 나오면 두 번째 비교 함수를 통해 두 객체를 비교한다.