안녕하세요. Brad입니다. 오늘은 불금이네요!! 설레는 마음을 뒤로하고 오늘 공부하면서 배운 내용들을 정리하도록 하겠습니다!! '좌표계산기' step4의 요구사항은 Point
를 3개 받았을 때 삼각형의 넓이를 구하여 출력하는 것인데요. 어제 배운 상속을 적용할 수 있었습니다.
고민되었던 부분은?
어떻게
if
문 중복을 최대한 줄일 수 있을까?이 문제는 어제 수업시간에도 질문했던 내용인데 숙제로 남겨졌던 내용입니다. 그때 Pobi가 준 힌트는 'Collection', '다형성' 이었는데요. 저보다 step이 앞선 여러 멤버들의 도움과 Pobi의 블로그(?!)에서 힌트를 얻을 수 있었습니다.
먼저 'Collection'은
HashMap
을 사용하여 key값에 따른 객체 생성을 하고, '다형성'은 상속 받은 객체에서 abstract메서드에 대하여 오버라이딩을 하여 각기 다르게 동작하도록 구현하여 해결할 수 있었습니다. 이렇게 설명하면 와닿지 않으니 코드를 보면서 설명하도록 하겠습니다./* CoordCalculator.java */ // 생략 static private Map<Integer, Figure> figures = new HashMap<>(); static { figures.put(NUM_FOR_LINE, new Line()); figures.put(NUM_FOR_TRIANGLE, new Triangle()); figures.put(NUM_FOR_SQUARE, new Square()); } // 생략 try { int pointsCount = points.size(); return new ResultDto(figures.get(pointsCount).calculateWide(points), pointsDto); } catch(Exception e) { return new ResultDto(pointsDto); } // 생략
먼저 Domain의 주요 로직을 처리를 하는
CoordCalculator
클래스에서HashMap
을 이용하여 각각의 key값에 따른 객체를 생성합니다. 이 때 Map의 Value의 제네릭 타입은Figure
이지만 Map에 넣어주는 값은 자식클래스의 객체임을 알 수 있습니다. 비록 자식클래스의 객체를 부모클래스로 형변환하여도 자식클래스에서 오버라이딩 내용을 불러올 수 있기 때문에 이렇게 처리 가능합니다.그럼 Map의 Value타입으로 왜 부모클래스 타입을 설정하였나?
그 이유는 만약 자식클래스가 여러 개의 타입으로 만들어져 있기 때문입니다. 하나의 자료구조로써 자식클래스를 모두 받아서 처리하기 위해선 부모클래스로 형변환을 한 후 때에 따라 자식클래스로 형변환을 하든 abstract메서드의 경우 그냥 부모클래스 타입으로 호출하여도 자식클래스의 오버라이딩된 메서드가 호출되기 때문에 그대로 사용할 수 있습니다! 따라서 위의 코드의 경우
figures.get(pointsCount).calculateWide(points)
의 부분은 figures라는HashMap
에서 자식클래스 객체로 생성 후 부모클래스로 형변환을 하고 자식클래스의 오버라이딩된 메서드를 호출하고 있습니다./* Figure.java */ public abstract class Figure { abstract double calculateWide(List<Point> points); }
/* Triangle.java */ public class Triangle extends Figure { @Override double calculateWide(List<Point> points) { Point p1 = points.get(0), p2 = points.get(1), p3 = points.get(2); double a = p1.calculateLength(p2); double b = p2.calculateLength(p3); double c = p3.calculateLength(p1); double s = (a + b + c) / 2; return Math.sqrt(s * (s - a) * (s - b) * (s - c)); } }
이런 상속의 구조가 되기 위해선 부모클래스인
Figure
을 추상클래스로 하여 부모클래스에서 바로 자식클래스의 메서드를 호출할 수 있도록 하고, 자식클래스인Triangle
에서는 이를 오버라이딩하여 실제 구현해두어야 합니다.
출력View에서 각 도형에 맞는 문구(예를들어 "사각형의 넓이는 ", "삼각형의 넓이는 ")를 어떻게 분기를 줄이면서 구현할 수 있을까?
가장 먼저 든 생각은 '위에서 다형성 이용한 것처럼 각 도형에서 문구 내용을 Overriding하고 이 String값을 전달할까?' 였습니다. 하지만 이러한 생각이 좋지 않을 것이라 생각한 이유는 이 내용은 아무리 봐도 View에서 처리해야할 내용이기 때문입니다. 출력View의 UI가 바뀐다고 했을 때 또는 이 문구의 내용이 바뀐다고 했을 때 Domain과는 연결성이 없어야 합니다! 그렇기 때문에
HashMap
을 다시 사용하여 포인트 개수에 맞는 출력 문구를 View에서 담당할 수 있도록 하였습니다.
이렇게 프로그램 내에서 부분적으로나마 상속으로 구현할 수 있는 부분은 상속으로 구현하니 코드의 길이도 짧아지고, 해당 프로그램에서 객체에 대해 설계한 부분이 좀 더 뚜렷해진다는 느낌을 받았습니다. 평소 상속을 구현할 때 모든 부분에서 상속이 이루어지는 객체들만 상속을 적용할 수 있다고 생각했는데 그러한 편견도 깰 수 있었습니다!!
오늘 추가적으로 공부한 부분
'TIL' 카테고리의 다른 글
Today's Dev Notes(2018-10-16) (0) | 2018.10.16 |
---|---|
Today's Dev Notes(2018-10-15) (0) | 2018.10.15 |
Today's Dev Notes(2018-10-10) (0) | 2018.10.10 |
Today's Dev Notes(2018-10-08) (0) | 2018.10.09 |
Today's Dev Notes(2018-10-05) (2) | 2018.10.05 |