티스토리 뷰

안녕하세요 Shiny Ocean입니다.

 

자바를 주제로한 세번째 포스팅은 추상 클래스에 대하여 다루어 보겠습니다.

 

 

추상클래스는 부모자식 클래스의 관계에서 자식클래스가 부모클래스를 상속받을때 클래스를 구현하는

기법으로 사용하며 전체적인 자바 프로그래밍의 방향성을 잡을때 사용합니다. 세부적인 내용은 나중에

클래스를 구현할때 디테일하게 다루고 큰 내용을 먼저 구상하고 선언할때 용이합니다.

 

 

두가지 예제 문제를 해결하며 자세히 알아보겠습니다.

 

 

 

Java 예제문제 3 -추상클래스 설계하고 사용해보기

단위를 변환하는 추상클래스 Converter가 있다,

1.. 추상클래스 Converter를 상속받아 원화를 달러로 변환하는 Won2Dollar 클래스를 작성하라

2.. 추상클래스 Converter를 상속받아 Km를 Mile로 변환하는 Km2Mile 클래스를 작성하라.

실행결과는 아래와같다.

조건1. Converter 클래스를 상속받는다. 조건2. 추상클래스의 내용을 프로그래머의 목적대로 사용할수 있도록 (이 문제에서는 거리단위변환, 외화단위 변환) 서브 클래스를 작성한다.

 

해결 과정)

1. Converter 추상클래스의 구성 알아보기.

 

p.290 ”추상메소드란 선언은 되어 있으나 코드가 구현되어 있지 않은, 즉 껍데기만 있는 메소드이다

p.291 “추상클래스의 종류에는 추상메소드를 포함하는클래스추상메소드가 없지만 abstract로 선언한 클래스 두가지가 있다.”

 

먼저 상속해주는 추상클래스가 어떤것인지 분석해봤습니다.

문제에서 제시된 converter추상클래스에는 convert,getSrcString,getDestString 세가지의

추상 메소드와 실행을 의미하는run이라는 메소드로 구성되어 있었습니다.

(세가지 추상메소드가 무엇을 의미하고 어떻게 작성되어야 하는지는 간단한 필기를 사진으로

첨부하였습니다.)

 

abstract class Converter {

public void run() {

                                 Scanner scanner = new Scanner(System.in);

                                 System.out.println(srcString() + " " + destString() + " 바꿉니다.");

                                 System.out.print(srcString() + " 입력하세요>> ");

                                 double val = scanner.nextDouble();

                                 double res = convert(val);

                                 System.out.println("변환 결과: " + res + destString() + "입니다");

                                 scanner.close();

                                  }

}

 

2. 추상클래스의 내용을 프로그래머의 목적대로 사용할수 있도록

(이 문제에서는 거리단위변환, 외화단위 변환) 서브 클래스를 작성한다.

서브클래스에서 상속받을 때의 코드작성을 추상클래스내의 추삼메소드를 작성하며 상속받아야 함으로 다음과 같이 코딩했습니다.

 

class Won2Dollar extends Converter {                           //추상클래스를 상속받음

                 public Won2Dollar(double ratio) {

                                 this.ratio = ratio;

                 }

                

                 @Override

                 protected double convert(double src) {

                                 return src/ratio;

                 }

 

                 @Override

                 protected String srcString() { return ""; }

 

                 @Override

                 protected String destString() { return "달러"; }

                

                

                 }

서브클래스에서 상속받을때 가장 중요한부분은 붉은색으로 표시한것처럼 추상화되어있던 메소드 내에 내용을(return, 연산등) 작성하여 클래스를 구현하는것입니다.

 

추상클래스내에서의 추상메소드는 어떻게 실행이될것이다는 방향만, 껍데기만 구성을해두고, 상속받은 서브클래스내의 추상메소드에서 프로그래머의 목적에 따라 구체적인 실행내용을 작성합니다.” , - 저는 추상클래스의 활용을 이렇게 이해했습니다.

  

똑같은 방법으로 거리를 변환해주는 서브클래스도 return되는 string과 클래스이름만 바꾸어작성했습니다

 

class Km2Mile extends Converter {                         //상속받는 추상클래스 동일, 클래스이름만 변경

                 public Km2Mile(double ratio) {

                                 this.ratio = ratio;

                 }

                

                 @Override

                 protected double convert(double src) {

                                 return src/ratio;

                 }

 

                 @Override

                 protected String srcString() { return "Km"; }                //리턴되는 스트링값변경

 

                 @Override

                 protected String destString() { return "Mile"; }

                

}

3. 메인 메소드에서 실행한다

 

저는 엮어둔 클래스들과 메소드들의 실행이 서로 얽히지 않게 메인메소드를 실행할 클래스를 Converting이라 따로 선언하였습니다. 그리고 메인메소드 내에 조건문을 통해 class Won2Dollar 실행할 것인가 class Km2Mile 실행할것인가를 입력받아 둘중하나를 실행할수 있도록 코딩후 마무리 했습니다.

 

 

 

 

전체 코드)

import java.util.Scanner;

 

abstract class Converter {

                 abstract protected double convert(double src); // 추상 메소드

                 abstract protected String srcString(); // 추상 메소드

                 abstract protected String destString(); // 추상 메소드

                 protected double ratio; // 비율

                

                 public void run() {

                                 Scanner scanner = new Scanner(System.in);

                                 System.out.println(srcString() + " " + destString() + " 바꿉니다.");

                                 System.out.print(srcString() + " 입력하세요>> ");

                                 double val = scanner.nextDouble();

                                 double res = convert(val);

                                 System.out.println("변환 결과: " + res + destString() + "입니다");

                                 scanner.close();

                 }

}

 

class Won2Dollar extends Converter {

                 public Won2Dollar(double ratio) {

                                 this.ratio = ratio;

                 }

                

                 @Override

                 protected double convert(double src) {

                                 return src/ratio;

                 }

 

                 @Override

                 protected String srcString() { return ""; }

 

                 @Override

                 protected String destString() { return "달러"; }

                

                

                 }

class Km2Mile extends Converter {

                 public Km2Mile(double ratio) {

                                  this.ratio = ratio;

                 }

                

                 @Override

                 protected double convert(double src) {

                                 return src/ratio;

                 }

 

                 @Override

                 protected String srcString() { return "Km"; }

 

                 @Override

                 protected String destString() { return "Mile"; }

                

}

                

public class Converting {

                 public static void main(String args[]) {

                                 Scanner scanner = new Scanner(System.in)

                                 int sw;

                                 System.out.println("<1. Won2Dollar>  ,  <2. Km2Mile> ");

                                 sw = scanner.nextInt();

                                 if(sw==1) {

                                                  Won2Dollar toDollar = new Won2Dollar(1200); // 1달러는 1200

                                                  toDollar.run();

                                                  System.out.println("실행완료, 프로그램을 종료합니다.");

                                 }

                                 if(sw==2) {

                                                  Km2Mile toMile = new Km2Mile(1.6); // 1마일은 1.6km

                                                  toMile.run();

                                                  System.out.println("실행완료, 프로그램을 종료합니다.");

                                 }

 

                                 scanner.close();

                 }

}

 

 

결과 콘솔)

 원화를 달러로 변환하는 Won2Dollar
Km를 Mile로 변환하는 Km2Mile

 

 

 

 

Java 예제문제 4 -추상클래스 설계하고 사용해보기

텍스트로 입출력하는 간단한 그래픽편집기를 만들자, 추상클래스 shape과 이를 상속받는

클래스코드 들을 잘 완성하고 아래의 예시처럼 “삽입”, “삭제”, “모두보기”, “종료” 4가지 그래픽

편집기능을 가진 클래스 GraphicEditor을 작성하라!

 

해결 과정)

처음 이문제에서의 추상클래스의 내용을 읽어보았을 제가 이해한 내용을 정리해보겠습니다.

 

1. 리스트를 활용한 저장공간 구현

2. draw라는 추상메소드를 편집한 서브 클래스들을 만들어 다양한 타입의 도형클래스 구현

3. 이들을 선언하며 리스트 내에 링크를 연결시키고 연결을 끊으며 삽입삭제를 수행하는 메소드 구현.

 

이해한 내용을 바탕으로으로 시작해 보았습니다

 

 

 

1.Shape 추상 클래스 분석하기.

이번 문제는 난이도가 많이 높게 느껴져서 p.321에있는 힌트를 바탕으로 추상클래스를 구성했습니다.

 

abstract class Shape {

                 private Shape next;

                 public Shape() { next = null;}

                 public void setNext(Shape obj) {next = obj;} // 링크 연결

                 public Shape getNext() {return next;}

                 public abstract void draw();    //추상메소드

}

기본적으로 Shape클래스 내의 메소드들은 draw()라는 추상메소드를 제외하곤

리스트를 구성하기 위한 메소드 들이었습니다. 필기로 정리해둔 내용을 첨부하겠습니다.

 

 

 

abstract class Shape {

}

 

<리스트의 원소 초기화 과정은 이렇게 될 것 같습니다.>

2. 추상클래스의 내용을 프로그래머의 목적대로 사용할수 있도록

(이 문제에서는 도형의 타입[ex: line rect circle]) 서브 클래스를 작성한다

 

추상클래스인 Shape을 상속받는 서브클래스이기 때문에 extends Shape이라 클래스를 작성하고 시작했습니다.

그리고 추상클래스 내의 추상메소드에는 없던 메소드의 내용을 구현했습니다.

class Line extends Shape {

                 @Override

                 public void draw() {

                                  System.out.println("Line");

                 }

}

class Rect extends Shape {

 

                 @Override

                 public void draw() {

                                  System.out.println("Rect");

                 }

 

}

class Circle extends Shape {

                 @Override

                 public void draw() {

                                  System.out.println("Circle");

                 }

 

}

 

3. 문제와 동일하게 인터페이스 구현

-그림과 같은 에디터 인터페이스 구성은 반복문과 조건문을 통해 설정했습니다

-종합적으로 지금까지 배운 반복문 조건문 입출력문들을 활용하여 코딩했습니다,

-코딩중 리스트내의 삽입과 삭제연산을 조건문안에 넣으니 코드가 복잡하게 되어 따로 메소드를 선언했습니다

 

<삽입메소드>

static void insert(int type) {

                                 Shape obj=null;

                                 switch (type) {

                                                  case 1: // Line

                                                                    obj = new Line();

                                                                    break;

                                                  case 2: // Rect

                                                                   obj = new Rect();

                                                                   break;

                                                  case 3: // Circle

                                                                   obj = new Circle();

                                 }

                                 if (start == null) { // 리스트가 비었을

                                                  start = end = obj;

                                 } else {

                                                  end.setNext(obj); // 마지막 원소 뒤에 삽입

                                                  end = obj;

                                 }

                 }

 

<삭제메소드>

static void del(int num){

                                 Shape test1 = start, test2 = start;

 

                                 if (start == null) { // 리스트가 경우

                                                  System.out.println("리스트가 비어있습니다.");

                                 }

                                 for (int i=0; i<num; i++) {

                                                  test2 = test1;

                                                  test1 = test1.getNext(); // num으로 받아온 숫자크기 만큼 삭제를 위한 리스트 생성 

                                                                   }

                                 if (start == end) { // 리스트에 원소가 한개밖에 없는 경우

                                                  start = end = null;

                                 }

                                 if (test1 == start) {// 첫번째 원소를 삭제하는 경우

                                                  start = start.getNext(); // 다음 원소가 첫번째 원소가

                                 }

 

                                 else if (test1 == end) {// 마지막 원소를 삭제하는 경우

                                                  end = test2; // 이전 원소가 마지막 원소가

                                                  end.setNext(null);

                                 } else {

                                                  test2.setNext(test1.getNext()); // 현재 원소를 리스트에서 삭제

                                 }

                 }

 

4. 디버깅을 하던도중 삭제연산에서 만약 리스트의 범위보다 인덱스가 더큰 값이 들어올 때 Null exception이 발생했습니다.

그래서 수업중에 배운 exception에러를 해결해줄수 있는 try, catch문을 사용하였습니다.

try {del(b);}  //(그냥del(b)라고 경우) b 리스트 원소 갯수보다 경우 Null exception발생  

                 catch(java.lang.NullPointerException e) {

                                 System.out.println("잘못된 입력입니다.");

                 }

 

 

 

전체 코드)

import java.util.Scanner;

 

abstract class Shape {

                 private Shape next;

                 public Shape() { next = null;}

                 public void setNext(Shape obj) {next = obj;} // 링크 연결

                 public Shape getNext() {return next;}

                 public abstract void draw();

}

 

class Line extends Shape {

                 @Override

                 public void draw() {

                                  System.out.println("Line");

                 }

}

class Rect extends Shape {

 

                 @Override

                 public void draw() {

                                  System.out.println("Rect");

                 }

 

}

class Circle extends Shape {

                 @Override

                 public void draw() {

                                  System.out.println("Circle");

                 }

 

}

 

public class GraphicEditor {

                 static Shape start=null; //리스트의 처음

 

                 static Shape end=null;    //리스트의  

 

                 public static Scanner s = new Scanner(System.in); //스캐너 변수

                 public static void main(String [] args) {

                                 System.out.println("그래픽 에디터 beauty 실행합니다.");

                                 int type = 0;      //작업의 유형을 받아냄 

                                 while (type != 4) { 

                                                  int a;        // 삽일할 도형의 유형 

                                                  int b;        // 삭제할 도형의 리스트 인덱스 

                                                  System.out.print("삽입(1), 삭제(2), 모두 보기(3), 종료(4)>>");

                                                  type = s.nextInt();

                                                  switch (type) {

                                                                   case 1:     // 삽입

                                                                                   System.out.print("Line(1), Rect(2), Circle(3)>>");

                                                                                   a = s.nextInt();

                                                                                   if (a < 1 || a > 3) {

                                                                                                    System.out.println("잘못 선택하셨습니다.");

                                                                                                    break;

                                                                                   }

                                                                                   insert(a);

                                                                                   break;

                                                                   case 2:     // 삭제

 

                                                                                   System.out.print("삭제할 도형의 위치>>");

                                                                                   b = s.nextInt();

                                                                                   try {del(b);}  

                                                                                   catch(java.lang.NullPointerException e) {

                                                                                                    System.out.println("잘못된 입력입니다.");

                                                                                   }

//(그냥del(b)라고 경우) b 리스트 원소 갯수보다 경우 Null exceptin발생

 

                                                                                   break;

                                                                   case 3:     // 모두 보기

                                                                                   int i=0;

                                                                                   Shape p = start;

                                                                                   while(p != null) {

                                                                                                    System.out.print(i+". ");

                                                                                                    p.draw();

                                                                                                    p = p.getNext();

                                                                                                    i++;

                                                                                   }

                                                                                   break;

                                                                   case 4:     // 끝내기

                                                                                   break;

                                                                   default:

                                                                                   System.out.println("잘못 입력하셨습니다.");

                                                  }

 

                                 }

                                 System.out.println("beauty 종료합니다.");

                 }

                 static void insert(int type) {

                                 Shape obj=null;

                                 switch (type) {

                                                  case 1: // Line

                                                                    obj = new Line();

                                                                    break;

                                                  case 2: // Rect

                                                                   obj = new Rect();

                                                                   break;

                                                  case 3: // Circle

                                                                   obj = new Circle();

                                 }

                                 if (start == null) { // 리스트가 비었을

                                                  start = end = obj;

                                 } else {

                                                  end.setNext(obj); // 마지막 원소 뒤에 삽입

                                                  end = obj;

                                 }

                 }

                 static void del(int num){

                                 Shape test1 = start, test2 = start;

 

                                 if (start == null) { // 리스트가 경우

                                                  System.out.println("리스트가 비어있습니다.");

                                 }

                                 for (int i=0; i<num; i++) {

                                                  test2 = test1;

                                                  test1 = test1.getNext(); // num으로 받아온 숫자크기 만큼 삭제를 위한 리스트 생성 

                                                                   }

                                 if (start == end) { // 리스트에 원소가 한개밖에 없는 경우

                                                  start = end = null;

                                 }

                                 if (test1 == start) {// 첫번째 원소를 삭제하는 경우

                                                  start = start.getNext(); // 다음 원소가 첫번째 원소가

                                 }

 

                                 else if (test1 == end) {// 마지막 원소를 삭제하는 경우

                                                  end = test2; // 이전 원소가 마지막 원소가

                                                  end.setNext(null);

                                 } else {

                                                  test2.setNext(test1.getNext()); // 현재 원소를 리스트에서 삭제

                                 }

                 }

 

결과 콘솔)

<null Exception 발생>

 

<디버깅 후 결과 콘솔창>

'Language > Java' 카테고리의 다른 글

Java - Class의 상속과 메소드 응용  (0) 2021.01.28
Java - 간단한 끝말잇기 텍스트게임 구현  (0) 2021.01.28
Java - Class & 생성자  (0) 2021.01.28
Java - Array & Exception처리  (0) 2021.01.28
Java - Basic  (0) 2021.01.28
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함