back-end-study / effective-java

🔥 이펙티브 자바 스터디
42 stars 4 forks source link

[item 14] Comparable을 구현할지 고려하라 #21

Closed jun108059 closed 1 year ago

jun108059 commented 2 years ago

PR이 늦어서 죄송합니다ㅠㅠ

youngreal commented 2 years ago

p89 3번째문단 중간 이후쯤에 이 클래스에 원래 클래스의 인스턴스를 가리키는 필드를두자. 그런다음 내부 인스턴스를 반환하는'뷰 메서드를 제공한다 라는 부분이 알것같으면서도 아리송해서 다른분이 이해하신이야기를 들어보고싶습니다 ㅎㅎ

jun108059 commented 1 year ago

@youngreal

p89 3번째문단 중간 이후쯤에 이 클래스에 원래 클래스의 인스턴스를 가리키는 필드를두자. 그런다음 내부 인스턴스를 반환하는'뷰 메서드를 제공한다 라는 부분이 알것같으면서도 아리송해서 다른분이 이해하신이야기를 들어보고싶습니다 ㅎㅎ

책에서 설명한 대로, 객체 지향적 추상화의 이점을 포기하고 '뷰' 메서드를 제공하면 아래와 같은 코드를 작성할 수 있습니다.

Point 클래스

class Point implements Comparable<Point> {
    private int x;
    private int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public int compareTo(Point point) {
        int result = Integer.compare(x, point.x);
        if (result == 0) {
            return Integer.compare(y, point.y);
        }
        return result;
    }
}

NamedPoint 클래스

class NamedPoint implements Comparable<NamedPoint> {
    // 원래 클래스의 인스턴스를 가르키는 필드
    private Point point;

    private String name;

    public NamedPoint(Point point, String name) {
        this.point = point;
        this.name = name;
    }
    // 내부 인스턴스를 반환하는 '뷰' 메서드
    public Point viewPoint() {
        return point;
    }

    @Override
    public int compareTo(NamedPoint namePoint) {
        int result = point.compareTo(namePoint.point);
        if (result == 0) {
            return name.compareTo(namePoint.name);
        }
        return result;
    }
}

이렇게 하면 NamedPoint 클래스에 원하는 compareTo 메서드를 새롭게 구현할 수 있게 되어 구체 클래스 Point에서 compareTo 일반 규약을 지킬 수 있게 됩니다.

Test 코드로 검증하면 아래와 같습니다.

class PointTest {

    @DisplayName("compareTo의 일반 규약을 지킬 수 있다")
    @Test
    void test() {
        Point point = new Point(1, 3);
        NamedPoint namedPoint = new NamedPoint(new Point(1, 2), "food");

        assertThat(point.compareTo(namedPoint.viewPoint())).isEqualTo(1);
        assertThat(namedPoint.viewPoint().compareTo(point)).isEqualTo(-1);
    }

}