Closed gmelon closed 1 year ago
아이템 10을 참고해 작성해보았습니다.
public class Point implements Comparable<Point> {
protected Integer x;
protected Integer y;
public Point(Integer x, Integer 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;
}
}
public class ColorPoint extends Point implements Comparable<Point>{
private Integer color;
public ColorPoint(Integer x, Integer y, Integer color){
super(x,y);
this.color=color;
}
@Override
public int compareTo(Point point) {
int result = super.compareTo(point);
if (result == 0) {
return Integer.compare(color, ((ColorPoint) point).color); // 잘못된 구현
}
return result;
}
}
public class PointTest {
public static void main(String[] args) {
Point point = new Point(1,2);
ColorPoint colorPoint = new ColorPoint(1,2,3);
System.out.println(point.compareTo(colorPoint));
System.out.println(colorPoint.compareTo(point));
}
}
이렇게 잘못된 다운 캐스팅이 되면 ClassCastException
이 됩니다. 아이템 10. equals는 일반 규약을 지켜 정의하라
에도 보면 구체 클래스를 확장해 새로운 값을 추가하면서 equals 규약을 만족시킬 방법은 존재하지 않는다.
고 나옵니다.
이를 해결하기 위해 뒤에 나오는 말처럼 이 클래스에 원래 클래스의 인스턴스를 가리키는 필드를 두자. 그런 다음 내부 인스턴스를 반환하는 '뷰' 메서드를 제공하면 된다.
를 구현해보면
class ColorPoint implements Comparable<ColorPoint> {
private Point point;
private int color;
public ColorPoint(Point point, int color) {
this.point = point;
this.color = color;
}
public Point asPoint() {
return point;
}
@Override
public int compareTo(ColorPoint colorPoint) {
int result = point.compareTo(colorPoint.point);
if (result == 0) {
return Integer.compare(color, colorPoint.color);
}
return result;
}
}
이렇게 중간에 asPoint로 원래 클래스인 Point의 인스턴스를 가리키도록 한 후에 테스트하게 되면 원하는 값을 얻을 수 있습니다.
public class Main {
public static void main(String[] args) {
Point point = new Point(1,2);
ColorPoint colorPoint = new ColorPoint(new Point(1,2),3);
System.out.println(point.compareTo(colorPoint.asPoint()));
System.out.println(colorPoint.asPoint().compareTo(point));
}
}
p.89에
기존 클래스를 확장한 구체 클래스에서 새로운 값 컴포넌트를 추가했다면 compareTo 규약을 지킬 방법이 없다
라고 했는데 이 부분 직관적으로 와닿지가 않아서 이에 대한 간단한 예시 코드가 궁금합니다