• [이펙티브 코틀린] hashCode의 규약을 지켜라

    2023. 4. 28.

    by. 하루플스토리

    반응형

    sealed한정자

    • sealed한정자는 외부 파일에서 서브 클래스를 만드는 행위 자체를 모두 제한한다. 외부에서 추가적인 서브클래스를 만들 수 없으므로 타입이 추가되지 않을 거라는게 보장된다.
    • 따라서 when 구문에서 else 처리를 하지 않아도 된다.

    equals를 직접 구현해야 하는 경우

    • 기본적으로 제공되는 동작과 다른 동작을 해야하는 경우
    • 일부 프로퍼티만으로 비교해야 하는 경우
    • data 한정자를 붙이는 것을 원하지 않거나, 비교해야하는 프로퍼티가 기본 생성자에 없는 경우

    hashCode의 규약을 지켜라

    • 오버라이드 할 수 있는 Any메서드로 hashCode가 있다. hashCode 함수는 수많은 컬렉션과 알고리즘에 사용되는 자료 구조인 해시 테이블을 구축할 때 사용됩니다.
    • 아주 긴 배열에서 요소가 포함되어 있는지 확인할 때 선형으로 비교하면 꽤 오랜 시간이 필요할 것이다. 성능을 좋게 만드는 해결 방법이 해시 테이블이다.
    • 해시테이블은 각 요소에 숫자를 할당하는 함수가 필요하다. 이 함수를 ‘해시 함수’라고 부르며 같은 요소라면 항상 같은 숫자를 리턴한다.
    • 해시코드의 규약
      • 어떤 객체를 변경하지 않았다면 hashCode는 여러 번 호출해도 그 결과가 항상 같아야 한다.
      • equals메서드의 실행 결과로 두 객체가 같다고 나온다면 hashCode 메서드의 호출 결과도 같다고 나와야 한다.
    • 코틀린은 equals 구현을 오버라이드 할 때 hashCode도 함께 오버라이드 하는 것을 추천한다. 같은 요소는 반드시 같은 해시코드를 가져야 하기 때문이다.
    • equals를 따로 정의했다면 반드시 hashCode도 함께 정의해 주어야 한다.
    • equals를 따로 정의하지 않았다면 정당한 이유가 없는 이상 hashCode를 따로 정의하지 않는 것이 좋다.

    CompareTo의 규약을 지켜라

    • compareTo 메서드는 Any클래스에 있는 메서드가 아니다. 이는 수학적인 부등식으로 변환되는 연산자이다.
    • compareTo는 다음과 같이 동작해야 한다.
      • 비대칭적 동작 : a ≥ b 이고 b ≥ a 라면 a == b 여야 한다.
      • 연속적 동작 : a ≥ b 이고 b ≥ c 이면 a≥c 여야 한다. 이러한 동작을 하지 못하면 요소 정렬이 무한 반복에 빠질 수 있다.
      • 코넥스적 동작 : 두 요소는 어떤 확실한 관계를 가지고 있어야 한다. 즉, a≥b 또는 b≥a 중에 적어도 하나는 항상 true 여야 한다.
    • 코틀린에서 compareTo를 따로 정의해야 하는 상황은 거의 없다. 일반적으로 어떤 프로퍼티 하나를 기반으로 순서를 지정하는 것으로 충분하기 때문이다.
    • String 끼리 비교하는 등 객체가 자연스러운 순서인지 확실하지 않다면 비교기 (comparator)를 사용하는 것이 좋다.

    API의 필수적이지 않는 부분을 확장 함수로 추출하라

    • 클래스의 메서드를 정의할 때는 메서드를 멤버로 정의할 것인지 아니면 확장함수로 정의할 것인지 결정해야 합니다.
    • 둘의 차이점을 설명하기 전에, 두 방식 중에 어떤 방식이 우월하다고 할 수 없다. 장 단점이 있으므로 상황에 맞게 사용해야 한다.
    • 멤버롸 확장의 가장 큰 차이점은 확장은 따로 가져와서 사용해야 한다는 것이다. 그래서 일반적으로 확장은 다른 패키지에 위치한다.
    • 상속을 목적으로 설계된 요소는 확장 함수로 만들면 안된다.
    • 멤버와 확장 함수의 차이
      • 확장 함수는 읽어 들여야 한다.
      • 확장 함수는 virtual이 아니다.
      • 멤버는 높은 우선 순위를 갖는다.
      • 확장 함수는 클래스 위가 아니라 타입 위에 만들어진다.
      • 확장 함수는 클래스 레퍼런스에 나오지 않는다.

    멤버 확장 함수의 사용을 피하라

    • 어떤 클래스에 대한 확장 함수를 정의할 때, 이를 멤버로 추가하는 것은 좋지 않다.
    • 특히, 가시성 제한을 위해 확장 함수를 멤버로 정의하는 것은 굉장히 좋지 않다.
    • 확장 함수의 가시성을 제한하고 싶다면 멤버로 만들지 말고 가시성 한정자를 붙여주면 된다.
    반응형

    댓글