TIL

(2024-04-26) 자바 개인 과제 level2

o_coding 2024. 4. 26. 20:04
package level2;

import java.util.Scanner;

import static java.util.regex.Pattern.matches;

public class Main {
private static final String OPER_REG = "[+\\-*/]";
public static void main(String[] args) throws Exception {
String stop;
double firstNum;
double secondNum;
String operator;

Calculator calculator = new Calculator(); //while문 전에 미리 객체 생성 
Scanner sc = new Scanner(System.in);

while (true) {
System.out.println("첫번째 숫자를 입력하세요 : ");
if(sc.hasNextDouble()){
firstNum = sc.nextDouble();
sc.nextLine();
}else{
throw new BadInputException("숫자를 입력하세요");
}
System.out.println("두번째 숫자를 입력하세요 : ");
if(sc.hasNextDouble()){
secondNum = sc.nextDouble();
sc.nextLine();
}else{
throw new BadInputException("숫자를 입력하세요");
}

System.out.println("연산자를 입력하세요 : ");
operator = sc.nextLine();
if(operator.matches(OPER_REG)){
double result = calculator.calculate(firstNum,secondNum,operator.charAt(0));
System.out.println(result);
}else{
throw new BadInputException("없는 연산자 입니다.");
}
System.out.println("더 계산하시겠습니까? (exit 입력 시 종료)");
stop = sc.nextLine();
if(stop.equals("exit")){
break;
} else if (stop.equals("look")) {
calculator.listLook();
}
}
}
}

계산 결과가 나오게 구현했고 Calculator객체 안에서 ArrayList로 저장 되도록 했다. 그런대 개발중 생긴 문제가 조회기능을 실행할 때 이전에 계산한 결과만 저장 되었는대 실수 했던 부분이 Calculator 객체를 선언하고 while문 안에서 new 로 생성 했는대 그 부분이 잘못되었던 거였다. 다음 계산을 할 때마다 새로 객체가 생성되어서 이전 기록들이 저장이 안되었던 거 였다.

 

그리고 다음 요구사항에 맞춰서 생성자로 값을 받도록 수정했는대 그러면 while문 안에 new로 Calculator 객체를 생성해야하는대 List가 유지 되도록 하려면 어떻게 할지 고민하다가 객체에 구애받지 않고 클래스자체에 적용되는 static 이 떠올라서 List를 static으로 선언했다.

private static List<Double> results = new ArrayList<>(); //스태틱 리스트

public Calculator(double firstNumber, double secondNumber, char operator){ //생성자
this.firstNumber = firstNumber;
this.secondNumber = secondNumber;
this.operator = operator;
}

 

level2최종 클래스 구조

public interface Operator {
public double operate(double firstNumber,double secondNumber);
}

사칙연산 인터페이스 

 

public class Calculator {
private double radius;
private double firstNumber;
private double secondNumber;
private Operator operator; //포함관계

Operator인터페이스 객체를 생성해 포함관계 구현

 

switch (operatorInput){
case "+":
operator = new AddOperator();
break;
case "-":
operator = new SubtractOperator();
break;
case "*":
operator = new MultiplyOperator();
break;
case "/":
operator = new DivideOperator();
break;
case "%":
operator = new ModOperator();
break;

}

메인클래스 메인 메소드에서 연산자 별로 객체를 생성하여 Operator형으로 만든 operator객체에 대입

 

public class ArithmeticCalculator extends Calculator {
private static List<Double> results = new ArrayList<>(); //객체를 새로 생성해도 적용되도록 static으로 선언

Calculator를 상속한 사칙연산 클래스 ArithmeticCalculator

public class CircleCalculator extends Calculator{
private static List<Double> results2 = new ArrayList<>(); //객체를 새로 생성해도 적용되도록 static으로 선언

Calculator를 상속한 원의넓이연산 클래스 CircleCalculator 둘다 연산 기록을 저장할수 있는 리스트를 static으로 둔다.

 

public static void listLook(){ //static List 참조를 위해 static 선언
results.stream().forEach(System.out::println);
}

스트림을 사용해 결과기록 리스트 출력

while (!stop) {
System.out.println("1.사칙연산");
System.out.println("2.원의 넓이");
System.out.println("3.사칙연산 기록 보기");
System.out.println("4.원의 넓이 기록 보기");
System.out.println("5.사칙연산 삭제");
System.out.println("6.원의 넓이 삭제");
System.out.println("0.종료");
select = sc.nextInt();
sc.nextLine();

최종 메인 메서드는 각 기능별로 번호를 입력하면 작동하도록했다.

과제 후 느낀점

:상속에 대해 더 이해할수 있었고 책임을 분리하도록 클래스를 나누면서 객체지향을 좀더 이해했다.static도 정확히 이해하지 못했었는대 과제를 하면서 static이 객체 생성 없이 접근이 가능하고 전역적으로 사용할 수 있다는걸 알았다.그리고 인터페이스와 상속을 통해 오버라이딩 도 구현을 했고 왜 오버라이딩이 필요한지 왜 업케스팅(부모클래스 타입 변수에 자식클래스객체를 할당)이 필요한지 조금은 이해했다.