계산기 만들기 프로젝트 마감 하루 전
Enum(열거형)
서로 관련있는 상수들끼리 모아 상수들을 대표할 수 있는 이름으로 타입을 정의하는 것
상수: 값이 한 번 정해지면 절대 변하지 않는 변수 → 자바에서 상수는 고정된(final) 값이고, 관례적으로 전부 대문자로 작성
추상 클래스처럼 동작할 수 있다. 내부에 필드, 생성자, 메서드까지 다 정의할 수 있다.
정해져 있는 한정된 데이터 묶음을 활용하기 좋다: ex) 월화수목금토일, 봄여름가을겨울, 주사위 숫자, 사칙연산!!?
public enum Operation { // 연산자 관리 및 연산 수행
PLUS('+', (a, b) -> a + b), // 람다식을 활용했더니 어마어마하게 간결해졌다...
MINUS('-', (a, b) -> a - b),
MULTIPLY('*', (a, b) -> a * b),
DIVIDE('/', (a, b) -> {
if (b == 0) {
throw new ArithmeticException("0으로 나눌 수 없습니다."); // 예외 던지기
}
return a / b;
});
private final char operator; // 속성
private final Calculator cal;
Operation(char operator, Calculator cal) { // 생성자
this.operator = operator;
this.cal = cal;
}
public double apply(double a, double b) { // 전달된 숫자에 대한 연산을 수행하고 반환
return cal.calculation(a, b);
}
public static Operation fromSymbol(char symbol) { // 입력된 연산자 매핑 메서드
for (Operation op : Operation.values()) {
// enum 안의 모든 상수를 배열로 반환 → 이유: 연산자가 어떤 상수와 연결될지 찾기 위해
if (op.operator == symbol) { // enum 상수가 가진 문자와 symbol이 같을 때
return op; // 그 같은 연산자(enum 상수)를 반환
}
}
throw new IllegalArgumentException("잘못된 연산 기호입니다.");
}
@FunctionalInterface // 람다식 활용을 위한 함수형 인터페이스
public interface Calculator {
double calculation(double a, double b);
}
}
처음엔 PLUS, MINUS 이렇게만 적어놓고 뭘 어떻게 해야하나 한참 보다가 괄호 안에 속성값을 집어 넣을 수 있음을 알게 됐고, 기존 switch 문에 '+' 연산자 대신 PLUS를 넣어서 구현되게 만들어본게 최선이었다. 정작 코드는 더 길어지고 복잡해졌고 enum을 활용함으로서 얻은게 없는 느낌... 분명히 입력 받은 연산자를 대입해서 그에 맞게 계산 후 반환할 방법이 있을텐데... 하며 한참 고민했으나 혼자 머리를 굴려서 답을 얻기 어려움에 되도록 ai보다는 구글링 위주로 enum에 대한 개념들과 활용 방법들을 찾아보다 힌트를 얻었다. 그렇게 scanner를 통해 전달 받은 연산자와 enum 메서드 안에 연산자가 같을 때 그 연산자를 반환하는 메서드를 만들기까지 도달했다. 그럼에도 코드는 매우매우 늘어졌다. apply를 추상메서드로 만들어서 각 기호마다 public int apply(int num1, int num2) {return num1 + num2;} 이런 식으로 공통의 인터페이스를 통해 각기 다른 연산을 수행하도록 만든 것은 공부가 되었으나 보기에 만족스럽진 않았다. 그러다 Stream 활용 파트를 진행할 때 전에 람다식에 대해 배웠던 부분들을 살펴보다 힌트를 얻어서 함수형 인터페이스로 만들고 그걸 활용해서 람다식으로 간결하게 작성할 수 있었다.
// 입력값 보다 큰 결과값들 출력 (Stream 활용)
List<Double> filtered = calculator.getResults().stream()
.filter(num -> num > Math.max(num1, num2)) // Math.max 두 숫자 중 큰 값
.toList();
System.out.println("입력값 보다 큰 결과값들만 출력됩니다.: " + filtered);
이제 마지막으로 제네릭만 남았다. 강의 때 들었던 내용을 읽어보고 <T> 여기저기 가져다가 T를 적어넣어봐도 마음처럼 되진 않았다. 나올 때 정수면 정수로 출력되게 실수면 실수로 출력되게 알아서 각자의 바구니에 들어갈 수 있게 만들어야 할 것 같은데, 아직 갈피를 잡지 못했다. 내일 제출마감 전까지 최대한 부딪혀보고 구현해보고 싶었으나 아직 못 해본 것들도 도전해보고 싶다. 내가 적은 코드들이지만 내 스스로 얼마나 이해하고 있을까 하는 생각이 든다. 다시 작성해보거나 각각의 코드들 사이에서 어떤 움직임이 있어지는지 더 공부해봐야겠다. 그리고 영어단어들에 뜻을 찾아보는 것도 꽤 도움이 될 것 같다. 작업 중간중간에 블로그에 중간 결과물들을 복붙 해놓거나 github에 올려두거나 해야겠다. 내가 어떤 문제들에 부딪혔었는지 남겨두고 다시 볼 수 있게 정리해보면 좋을 듯 하다.