public class Figure {
	//왼쪽위의 점과 오른쪽 아래의 점으로 이루어진 직각사각형 안에 도형이 그려진다.
	private int left, up;
	private int right, down;
	
	public Figure(int left, int up, int right, int down) {	//지난번 Rec은 좌표평면기준, 이번Figure은 그림판기준
		if(right < left) {	//콘솔서 잘못입력했을 때, 값을 옮겨주기
			int tmp =  right;
			right = left;
			left = tmp;
		}
		
		this.left = left;
		this.right = right;

		if(down < up ) {
			int tmp = down;
			down = up;
			up = tmp;
		}
		
		this.up = up;
		this.down = down;
	}
	public void moveRD(int right, int down) {
		this.right = right;
		this.down = down;
	}
	public void moveLU(int left, int up) {
		this.left = left;
		this.up = up;
	}
	public void print() {	
		System.out.println("좌상점: " + left	 + "px , " + up + "px");
		System.out.println("우하점: " + right + "px , " + down + "px");

	}//좌표이동을 위한 Rect
	public int getLeft() {
		return left;
	}
	public int getUp() {
		return up;
	}
	public int getRight() {
		return right;
	}
	public int getDown() {
		return down;
	}
}

상속받은 사각형 클래스

public class Rect extends Figure {

		private int w;
		private int h;
		
		
		public Rect(int left, int up, int right, int down) {
			super(left, up, right, down);
			//w = right - left; 
			w = getRight() - getLeft();
			h = getDown() - getUp();
		}
		@Override
		public void print() {
			System.out.println(" <<사각형입니다>>");
			super.print();
			System.out.println("가로 : " + w);
			System.out.println("세로 : " + h);
		}
}

상속받은 원형 클래스

public class Circle extends Figure {

	/* 원을 그릴 때, 좌상점과 우하점으로 그린다며 중심점은 실수로 해야한다.
	 * 예 : (0,0) (1,1)인 원에서 중심점은 (0.5,0.5)
	 * 
	 * 원을 그릴 때, 좌상점과 우하점으로 그린다면 원이 아닌 타원이 나올 수 있다.
	 * 예 : (0,0) (2,3)은 타원
	 * 
	 * 위와 같은 이유 때문에 원을 그릴 때는 중심점과 반지름을 기준으로 그릴 것이다.
	 * */
	private int x, y; 	//중심점의 x좌표, y좌표
	private int r;		
	
	
	public Circle(int x, int y, int r) {
		super(x-r, y-r, x+r, y+r);
		this.x=x;
		this.y=y;
		this.r=r;
	}
	@Override
	public void print() {	//좌상점 우하점이 중요한 도형이 아니라서 부모클래스를 호출하지 않아도 돼
		System.out.println("<<원입니다>>");
		System.out.println("중심점 : " + x + "px , " + y + "px");
		System.out.println("반지름 : " + r);
	}
}

결과값의 클래스

import java.util.Scanner;

public class FigureTest {	//클래스의 형변환이 왜 필요한가를 이해하기 위한 예제

	public static void main(String[] args) {	//클래스형변환을 통해, 하나의 클래스로 관리를 해야하는 이유를 알아볼 예정

	// Rect이랑 Circle파일 출력할라고 불러온 값들인데 딴거한다고 숨겼음	
	//	Rect r = new Rect (167, 255, 278, 391);
	//		r.print();
			
	//	Circle c = new Circle (5,10,5);
	//		c.print();

		
		Figure []arr = new Figure[10];	//간단하게 하려고 배열10개짜리 넣은거임, 원랜 제한이 없게해야한대	
		int maxCount = 0;				//최대로 그린 도형의 갯수
		int pos = 0;					//현재 도형의 번호(되돌리기나 뒤로가기하면 갯수가 줄어드니까)
		int menu = 0;
		Scanner scan = new Scanner(System.in);
		
		do {
			System.out.println("----------------------");
			System.out.println("1. 도형 그리기");
			System.out.println("2. 실행 취소");
			System.out.println("3. 다시 실행");
			System.out.println("4. 확인 하기");
			System.out.println("5. 종료 하기");
			System.out.println("----------------------");
			System.out.println("메뉴 선택 : ");
			menu = scan.nextInt();
			
			switch(menu) {
			case 1:	
				System.out.println("그릴 도형을 선택하세요. (1.원, 2.사각형)");
				int selectFigure = scan.nextInt();
				switch(selectFigure) {
					case 1:
						System.out.println("중심점을 입력하세요(예: 10 10) : ");
						int x = scan.nextInt();
						int y = scan.nextInt();
						System.out.println("반지름을 입력하세요 : ");
						int r = scan.nextInt();
						arr[pos++] = new Circle(x,y,r); //다입력받고 객체만들기
						maxCount = pos;	//되돌리기하면 이전에 했던 작업을 날려야되니까 이 작업을 해줘야함
						break;
					case 2:
						System.out.println("좌상점을 입력하세요(예: 10 10) : ");
						int left = scan.nextInt();
						int up = scan.nextInt();
						System.out.println("우하점을 입력하세요(예: 10 10) : ");
						int right = scan.nextInt();
						int down = scan.nextInt();
						arr[pos++] = new Rect(left, up, right, down);		//후의? 증감연산자 덕분에 pos+=1; 또는 pos++ 대신에 
						maxCount = pos; 									//배열생성의 번지번호에 ++넣어서 반복할때 하나씩 자동으로 올릴 수 있음
						break;
					default:
						System.out.println("없는 도형입니다.");
				}
				break;
			case 2: 
				if(pos != 0) {	//없는데 뺄 순 없으니까 0아닌거 확인하기
					pos--;	
				}
				break;
			case 3: 
				if (pos < maxCount) {
					pos++;
				}
				break;
			case 4: 
				for(int i = 0; i<pos; i++) {
					arr[i].print();
				}
				break;
			case 5: 
				break;
			}
		}while(menu != 5);
		scan.close();
		//배열하나에 한번에 원, 사각형 묶어서 넣어두면 실행취소 상황에 어느것이 이전 단계였는지 기억을 하는 코드를 추가작업하거나 관리하기 어렵기때문에 
		//한번에 클래스의 형변환으로 동시관리를 한다면 값을 다루기가 수월하다.
	}
}