[JAVA] 계산기 만들기3 - 트러블 슈팅🛠️ (Object, Lambda)

림민지·2025년 3월 6일

Today I Learn

목록 보기
18/62
  1. 코드 중복 삭제
  2. 자료형 변경
  3. Lambda & Enum 활용하기

1️⃣ 코드 불필요한 중복 삭제

1. 기존 코드 리팩토링

기존 코드에서 Setter를 설정하기 위해 CalculatorClass에서
private double result=0;으로 result값을 설정해줬었다.
하지만 이는 코드의 중복을 만들고 있었다.

public class CalculatorClass {
    private ArrayList<Double> calculateList = new ArrayList<>(); //연산 결과 저장하기
    
    private double result=0;

    public void setResult(double result){ //setter 설정하기
        this.result = result; //코드 중복
        calculateList.add(result);
    }
    
    int add(int a, int b){    //더하기
    	int result = a+b;
        return result;
    }

때문에 private result 선언을 지우고

public class CalculatorClass {
    private ArrayList<Double> calculateList = new ArrayList<>(); //연산 결과 저장하기

    public void setResult(double result){//setter 설정하기
        calculateList.add(result);
    }
    int add(int a, int b){    //더하기
        return a+b;
    }

바로 return값에 저장할 수 있도록 설정했다.

2️⃣ Object 자료형 이용하기✨

지금 내가 짠 코드를 활용하서 계산기 결과를 출력하면 int 타입의 값으로 나와도 꼭 뒤에 소수점이 붙어 출력되는 문제점이 있었다.
소수점이 붙으면 double로, 아니면 int로 저장될 수 있도록 설정해보자!

📌 Object란?
자바에서 모든 클래스의 부모(최상위 클래스)!
→ 모든 데이터 타입(int, double, String, ArrayList 등)을 저장할 수 있는 자료형

Object는 어떤 타입이든 저장할 수 있기 때문에 int든 double이든 다 저장할 수 있다~!
CalculateClass를 고쳐보자.
(1) 변수 타입을 Object로 변경

private ArrayList<Object> calculateList = new ArrayList<>(); //연산 결과 저장하기

//setter 설정하기
public void setResult(Object result){
	calculateList.add(result);
    }

(2) 나누기는 double int 두가지 타입이 다 나올 수 있으니 경우의 수를 나누어 처리

Object divide(int a, int b) {
	if (b==0){
    	throw new ArithmeticException("0으로는 나눌 수 없습니다");
        }
    if (a % b == 0) {  // 나머지가 없으면 int 반환
    	return a / b;
        } else {  // 나머지가 있으면 double 반환
            return (double) a / b;
        }
    }

(3) main 클래스에서 result 변수 타입도 변경해주자

//결과값 변수 설정하기
Object result = 0;

이렇게하면 저장되는 변수의 타입을 하나로 통일하지 않고도 저장 가능하다!


3️⃣ Enum & Lambda

1. 기존 코드의 문제점과 개선 필요성

🚧 기존 코드 (CalculatorClass2 클래스)

기존 CalculatorClass2에서는 사칙연산 (+, -, *, /)을 개별 메서드로 구현하고, 연산 결과를 ArrayList<Object>에 저장하는 구조

❌ 기존 코드의 문제점

  1. 연산자 추가가 번거로움
    : 나중에 제곱이나 루트같은 연산을 추가하려면 메서드를 아예 새로 만들어야 했음
  2. if-else 또는 switch 문 필요
    : 연산자를 문자열로 입력받아서 switch 문으로 처리해야했음.
    → 연산이 많아지면 차후 관리의 어려움이 생길 수 있을 것 같았음
  3. 코드의 복잡성
    : 하나의 CalculatorClass2 파일에 모든 메서드가 다 들어있으니 가독성이 떨어지고 복잡해보였음

2. 개선 방법: Enum을 활용한 연산자 처리

📌 개선 코드 (OperatorType 클래스)

: OperatorType Enum파일을 만들어서 연산자를 정의, Lambda 표현식
→ 연산 로직을 직접 연결

public enum OperatorType {
    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 String operator;
private final BiFunction<Integer, Integer, Object> operation;
  • operation을 BiFunction<Integer, Integer, Object>으로 정의해서, 앞의 두가지 타입으로 입력을 받고, 세번째 타입으로 반환하게 했다.
  • final을 붙여서 상수취급 받을 수 있도록 변호나
    → 각 연산자(+, -, *, /)가 고유한 연산을 가지며, 실행 중에 바뀌지 않도록 보장
  • private : 객체 외부에서 직접 접근하지 못하게 함
    apply(), findOperator() 메서드로만 접근 가능하도록
 // 연산 수행 메서드
    public Object apply(int a, int b) {
        return operation.apply(a, b);
    }
// Enum에서 입력받은 연산자에 맞는 연산 찾아서 계산하기
public static OperatorType findOperator(String operator) {
	for (OperatorType value : OperatorType.values()) {
    	if (value.operator.equals(operator)) {
        	return value;
            }
        }
        throw new IllegalArgumentException("잘못 입력하셨습니다: " + operator);
    }

나머지 메서드(리스트(ArrayList), 연산 기록 저장(setter)&반환(getter)&지우기(remove))들을 ArithmeticCalculator 클래스를 만들어서 따로 관리!
💊 캡슐화 성공~~!

파일 구조가 이렇게 바뀌게 된다!

📦 JavaCalculator
┣ 📂out
┣ 📂src
┃ ┣ 📂 MakeCalculator3 
┃ ┃  ┣  ArithmeticCalculator.java //나머지 메서드 저장 클래스
┃ ┃  ┣  CalculatorMain3.java //메인클래스
┃ ┃  ┗  OperatorType.java //연산자 저장된 enum
┃ ┃ 
┗ 📜 README.md

3. 적용 뒤 장점

  1. OperatorType에 연산자와 연산 로직을 함께 정의하여 가독성↑ + 유지보수 쉬움.
  2. 향후 연산자 추가가 간단해짐
    : 새로운 연산을 추가할 때, Enum 항목만 추가하면 됨.
    ex) 제곱(Power, (a, b) -> Math.pow(a, b))을 쉽게 추가 가능.
  3. switch 문 제거
    : findOperator() 메서드를 통해 입력된 연산자를 자동으로 찾는다
  4. 코드의 캡슐화

4️⃣ Generic 적용하기

제네릭 설명 글
🔗 https://velog.io/@minjee2758/Generic-%EC%A0%9C%EB%84%A4%EB%A6%AD

나는 Generic을 다루는 것이 매우 서툴기 때문에 기존 코드를 보호하기 위해 브랜치 만들어 나눠서 작업했다. branch MakeGeneric🪵

profile
@lim_128

0개의 댓글