여러 자료를 보며 내가 이해한 제네릭이란 메서드나 클래스의 타입에 대한 지정을 최초 생성시에 하는 것이 아닌 인스턴스를 만들 때 외부에서 지정해주는 것이었다.
한마디로 핵심은 외부에서 타입을 지정해 준다는 것!
1. 첫번째 시도
- 계산의 결과를 담는 results 배열의 타입을 제네릭으로 지정해주고, 계산을 수행하는 calculate 메서드의 리턴타입과 매개변수 타입을 동일한 제네릭으로 선언
- Operator ‘+’ cannot be applied to ‘T’, ‘T’ 에러 발생
public class A<T> {
private ArrayList<T> results = new ArrayList<>();
public T calculate(T number1, T number2){
results.add(number1);
return number1 + number2;
}
}
gpt 에게 물어본 결과, 제네릭인 T타입이 어떤 데이터 타입이 올 수 있을지 모르기 때문에 '+'연산 자체를 지원하는지 여부도 알 수 없기 때문에 에러가 났다고 알려줬다 -> 결론적으로 "타입의 제한이 필요하다"는 결론이 나왔다
2. 두번째 시도
제네릭의 타입 제한 : <K extends T> - K는 T이거나 T를 상속받은 하위타입이어야 함
- 피연산자의 타입을 Number의 하위 타입만 받을 수 있게 가능하도록 제한함
- 동일한 에러 발생
public class A<T extends Number> {
private ArrayList<T> results = new ArrayList<>();
public T calculate(T number1, T number2){
results.add(number1 + number2);
return result;
}
}
타입의 제한을 걸어주었지만, Integer가 들어오는 경우와 Double이 들어오는 경우에 따라서 더하기 연산을 수행하면 결과타입이 double이 될지 int가 될지 자바 컴파일러는 모르기 때문에 에러가 난 것 같다
이 부분에서 시간이 꽤 들었는데 그 이유는 아래의 예시는 잘 작동이 됐었기에 당연히 각각의 타입을 알아서 구분하고 더하기까지 해줄 수 있을 거라고 생각해서 그랬던 것 같다🙄
3. 세번째 시도
메서드 수준에서의 제네릭 : public <T> Double calculate(T number1, T number2), return 타입 앞에 <T> 붙이기
- calculate 메서드의 return 타입을 Double로 지정해 주고, results 의 타입 또한 Double로 지정
- 값이 정수로 들어오든, 부동소수점형으로 들어오든지 간에 정확한 계산 결과값을 보여주기 위해서는 Double로 고정하는 게 좋다고 생각했기 때문이다!
public class A {
private ArrayList<Double> results = new ArrayList<>();
public <T extends Number> Double calculate(T number1, T number2){
Double result = number1.doubleValue() + number2.doubleValue();
results.add(result);
return result;
}
}
완성! 이제 이 코드를 바탕으로 과제에 반영해보았다
4. 완성
피연산자에 정수를 넣어도 실수를 넣어도 결과가 정확하게 나왔다!
public class ArithmeticCalculator {
private OperatorType addOperator = OperatorType.ADD;
private OperatorType subtractOperator = OperatorType.SUBTRACT;
private OperatorType divideOperator = OperatorType.DIVIDE;
private OperatorType multiplyOperator = OperatorType.MULTIPLY;
private ArrayList<Double> results = new ArrayList<>();
public <T extends Number> Double calculate(T number1, T number2, char operator){
double answer = 0.0;
//연산 수행
if (operator == addOperator.getOperator()) {
answer = number1.doubleValue() + number2.doubleValue();
} else if (operator == subtractOperator.getOperator()) {
answer = number1.doubleValue() - number2.doubleValue();
} else if (operator == multiplyOperator.getOperator()) {
answer = number1.doubleValue() * number2.doubleValue();
} else if (operator == divideOperator.getOperator()) {
answer = number1.doubleValue() / number2.doubleValue();
}
results.add(answer);
return answer;
}
public String getAllResults(){
return results.toString();
}
public Double getResults(int index){
return results.get(index);
}
public void setResult(int index, double value){
results.set(index, value);
}
public void deleteFirstResult(){
results.remove(0);
}
}
추가적으로 안 것
추가적으로 이번 과제를 하면서 git에 시간을 엄청 많이 쓴 것 같다 ㅎㅎ...
잘못 올린 커밋 메시지를 수정하고 싶어서 vim에서 esc후 :wq를 아무리 눌러봐도 아무런 동작도 일어나지 않았다 ㅠㅠ
거의 몇시간동안 시도해보고... 심지어 친구 노트북으로도 똑같이 수행해봤는데 너무 잘 되서 계속 스트레스를 받던 도중에 나의 경우는 vim이 아니라 Nano가 기본 편집기로 설정되어 있다는 것을 깨닫고 해결했다,,,
Push 후 Commit 수정
https://kyn1013.tistory.com/167
그 다음으로는 실수로 이상하게 연속적으로 커밋한 기록을 발견하고 push가 끝난 후의 커밋을 삭제하는 방법도 알게 됐다
Push 후 Commit 삭제
https://kyn1013.tistory.com/175
'JAVA' 카테고리의 다른 글
Enum 및 예외처리를 적용한 계산기 만들기 (0) | 2025.01.10 |
---|---|
Lambda & Stream을 이용하여 특정 값보다 큰 값들만 조회하기 (0) | 2025.01.09 |
다형성을 이용한 계산기 만들기 - 예외처리 추가 (0) | 2025.01.07 |
다형성을 이용한 계산기 만들기 (0) | 2025.01.06 |
자료구조 요리 레시피 메모장 만들기 / Iterator (1) | 2025.01.02 |