계산기 3레벨 요구 사항
3. Enum, 제네릭, 람다 & 스트림을 이해한 계산기 만들기
- [ ] 현재 사칙연산 계산기는 (➕,➖,✖️,➗) 이렇게 총 4가지 연산 타입으로 구성되어 있습니다.
- [ ] Enum 타입을 활용하여 연산자 타입에 대한 정보를 관리하고 이를 사칙연산 계산기 ArithmeticCalculator 클래스에 활용 해봅니다.
- 예시 코드(기존에 작성했던 양의 정수 계산기를 수정)
- public enum OperatorType { /* 구현 */ } public class ArithmeticCalculator /* Hint */ { /* 수정 */ }
- [ ] 실수, 즉 double 타입의 값을 전달 받아도 연산이 수행하도록 만들기
- [ ] 키워드 : 제네릭
- [ ] 단순히, 기존의 Int 타입을 double 타입으로 바꾸는 게 아닌 점에 주의하세요!
- [ ] 지금까지는 ArithmeticCalculator, 즉 사칙연산 계산기는 양의 정수(0 포함)를 매개변수로 전달받아 연산을 수행
- [ ] 피연산자를 여러 타입으로 받을 수 있도록 기능을 확장
- [ ] ArithmeticCalculator 클래스의 연산 메서드(calculate)
- [ ] 위 요구사항을 만족할 수 있도록 ArithmeticCalculator 클래스를 수정합니다. (제네릭)
- [ ] 추가적으로 수정이 필요한 다른 클래스나 메서드가 있다면 같이 수정 해주세요.
- 예시 코드(기존에 작성했던 양의 정수 계산기를 수정)
- public class ArithmeticCalculator /* Hint */ { /* 수정 */ }
- [ ] 키워드 : 제네릭
- [ ] 저장된 연산 결과들 중 Scanner로 입력받은 값보다 큰 결과값 들을 출력
- [ ] ArithmeticCalculator 클래스에 위 요구사항을 만족하는 조회 메서드를 구현합니다.
- [ ] 단, 해당 메서드를 구현할 때 Lambda & Stream을 활용하여 구현합니다.
- [ ] Java 강의에서 람다 & 스트림을 학습 및 복습 하시고 적용 해보세요!
[ ] 추가) 람다 & 스트림 학습을 위해 여러 가지 조회 조건들을 추가하여 구현 해보시면 학습에 많은 도움이 되실 수 있습니다.
계산기 3레벨의 요구사항은 enum과 제네릭, 람다 스트림을 써보는 것이다.
처음에는 익숙한 추상화 메소드를 오버라이드 하여 해봤다.
public enum OperatorType {
익명 클래스
Add{
@Override
public double operate(double firstNumber, double secondNumber) {
return firstNumber + secondNumber;
}
},
Divide{
@Override
public double operate(double firstNumber, double secondNumber) {
return firstNumber / secondNumber;
}
},
Multiply{
@Override
public double operate(double firstNumber, double secondNumber) {
return firstNumber * secondNumber;
}
},
Subtract{
@Override
public double operate(double firstNumber, double secondNumber) {
return firstNumber - secondNumber;
}
};
private String symbol;
OperatorType(String symbol){
this.symbol = symbol;
}
public abstract double operate(double firstNumber, double secondNumber);
추상화 메소드를 오버라이드 하여 사용해보는건 딱히 어렵지 않았지만 Enum에 람다식을 활용하는 것은 Enum에 익숙하지도 않고 람다식도 처음 써보는거라 같은 조원 분의 코드를 보면서 이런식으로 쓰는건지 감을 잡고 검색도 많이 했다.
람다식을 활용한 Enum
Add ("+", Double::sum),
Subtract ("-", (x,z) -> x - z),
Multiply ("*", (x,z) -> x * z),
Divide ("/", (x,z) -> x / z);
private final String symbol;
private final BiFunction<Double, Double, Double> fun;
// BiFunction<T, U, V>
OperatorType(String symbol, BiFunction<Double, Double, Double> fun) {
this.symbol = symbol;
this.fun = fun;
}
public double calculate(double x, double z) {
return fun.apply(x, z);
}
public static OperatorType getOp(String operator){
return Arrays.stream(OperatorType.values()).filter(oper -> oper.symbol.equals(operator)).findFirst().
orElseThrow(() -> new IllegalArgumentException(operator + " is not a valid operator"));
}
public String getSymbol(){
return symbol;
}
}
BiFunction 인터페이스는 세개의 제네릭 타입을 사용합니다.
T : 첫 번째 매개변수 타입
U : 두 번째 매개변수의 타입
R : 반환 타입입니다.
인터페이스 내부에는 추상 메서드 apply()가 있습니다.apply() 메서드는 제네릭 타입인 두개의 매개변수를 전달 받아 특정 작업을 수행한 후 값을 반환합니다.
람다식에선 stream의 filter() 메서드를 이용하여 전달 받은 연산기호와 OperaterType enum의 값과 비교하여 맞는 것을 찾아 그 값을 리턴해주고 그 리턴 받은 값으로 OperatorType 객체인 oper에 대입 해줍니다.
public void setUpOperation(String operation) throws Exception{
if(Pattern.matches(Reg.OPERATION_REG.reg, operation)){
this.oper = oper.getOp(operation);
}
else{
throw new BadInputException("연산 기호");
}
}
오늘은 enum을 써보면서 람다, 스트림도 맛 만봤는데 아직 많이 모르는게 많고 알면 알수록 더 어려워지는 것 같다.내일은 제네릭 클래스까지 사용해 봐야겠다.
'TIL' 카테고리의 다른 글
[TIL] 9월 13일 (1) | 2024.09.13 |
---|---|
[TIL] 숫자 야구 게임 만들기 (2) | 2024.09.12 |
[TIL] 계산기 3레벨 마무리 (1) | 2024.09.10 |
[TIL] 오늘은 금요일 ! (1) | 2024.09.06 |
[TIL] 오늘 (7) | 2024.09.04 |