이번엔 계산기 과제 lv.3 ~ lv.4까지의 내용을 다뤄보자
lv.3의 목표는 각각 연산 클래스를 만들고 Calculator
클래스와 적절한 관계를 맺는것이다.
처음엔 클래스간의 관계라길래 당연히 상속
을 생각하고 코드를 작성했다
음.. 근데 하려면 할 수 있을거같은데 뭔가 굉장히 힘든길을 가는 느낌이 계속 드는 것이다.
그렇게 계속 고민하는 중인데
한 팀원분이 튜터분께 질문한 결과 상속
을 하도록 낸 과제는 아닌?
정확히 기억은 안나지만 어쨋든 상속은 안써도 된다는 말로 들었다
아하? 그래서 바로 그냥 연산에 대한 클래스들만 작성하고
Calculator
클래스 내부에 인스턴스를 생성해줬다.
import UIKit
class Calculator {
let addOperation = AddOperation()
let subtractOperation = SubtractOperation()
let multiplyOperation = MultiplyOperation()
let divideOperation = DivideOperation()
let remainderOperation = RemainderOperation()
// calculate 함수 정의
func calculate(operator: String, firstNumber: Double, secondNumber: Double) -> Double? {
switch `operator` {
case "+":
return addOperation.operate(firstNumber: firstNumber, secondNumber: secondNumber)
case "-":
return subtractOperation.operate(firstNumber: firstNumber, secondNumber: secondNumber)
case "*":
return multiplyOperation.operate(firstNumber: firstNumber, secondNumber: secondNumber)
case "/":
return divideOperation.operate(firstNumber: firstNumber, secondNumber: secondNumber)
case "%":
return remainderOperation.operate(firstNumber: firstNumber, secondNumber: secondNumber)
default:
return -1
}
}
}
class AddOperation {
func operate(firstNumber: Double, secondNumber: Double) -> Double {
return Double(firstNumber + secondNumber)
}
}
class SubtractOperation {
func operate(firstNumber: Double, secondNumber: Double) -> Double {
return Double(firstNumber - secondNumber)
}
}
class MultiplyOperation {
func operate(firstNumber: Double, secondNumber: Double) -> Double {
return Double(firstNumber * secondNumber)
}
}
class DivideOperation {
func operate(firstNumber: Double, secondNumber: Double) -> Double {
return Double(firstNumber) / Double(secondNumber)
}
}
class RemainderOperation {
func operate(firstNumber: Double, secondNumber: Double) -> Double {
return firstNumber.truncatingRemainder(dividingBy: secondNumber)
}
}
요게 각 연산 클래스와 내부를 변경한 calculator
클래스이다
calculator
는 크게 변경한 것은 없고 각 연산 클래스의 선언과
계산식을 직접 넣는대신에 클래스를 호출하여 연산하는 식을 변경했다.
그러다가 굳이 switch
문을 사용하지 않아도 되겠다는 생각이 들어서 calculator
클래스를 아래와 같이 수정했다
class Calculator {
let addOperation = AddOperation()
let subtractOperation = SubtractOperation()
let multiplyOperation = MultiplyOperation()
let divideOperation = DivideOperation()
let remainderOperation = RemainderOperation()
func add(firstNumber: Double, secondNumber: Double) -> Double {
return addOperation.operate(firstNumber: firstNumber, secondNumber: secondNumber)
}
func subtract(firstNumber: Double, secondNumber: Double) -> Double {
return subtractOperation.operate(firstNumber: firstNumber, secondNumber: secondNumber)
}
func multiply(firstNumber: Double, secondNumber: Double) -> Double {
return multiplyOperation.operate(firstNumber: firstNumber, secondNumber: secondNumber)
}
func divide(firstNumber: Double, secondNumber: Double) -> Double? {
return divideOperation.operate(firstNumber: firstNumber, secondNumber: secondNumber)
}
func remainder(firstNumber: Double, secondNumber: Double) -> Double {
return remainderOperation.operate(firstNumber: firstNumber, secondNumber: secondNumber)
default:
return 0
}
}
}
그리고 아래 부분은 바뀐 calculator
클래스에 맞게 바꾼 호출 부분이다
let calculator = Calculator()
// 각 연산 메서드를 호출하여 계산
let addResult = calculator.add(firstNumber: 10, secondNumber: 5)
print("addResult : \(addResult)")
let subtractResult = calculator.subtract(firstNumber: 10, secondNumber: 5)
print("subtractResult : \(subtractResult)")
let multiplyResult = calculator.multiply(firstNumber: 10, secondNumber: 5)
print("multiplyResult : \(multiplyResult)")
if let divideResult = calculator.divide(firstNumber: 10, secondNumber: 5) {
print("divideResult : \(divideResult)")
}
let remainderResult = calculator.remainder(firstNumber: 10, secondNumber: 15)
print("remainderResult : \(remainderResult)")
lv.3는 처음에 클래스의 관계 라는점을 깊게 생각해서 어렵게 느껴졌는데 막상 다른 방법으로 구현하니 생각했던것보다는 할만했다.
그러나 아직 클래스에 대한 작성법? 구현하는데 있어서 어색한 면이 있어서
좀 더 연습해봐야할것같다.
다음은 과제의 마지막인 lv.4!
lv.1~lv.3가 필수 구현이고 lv.4는 선택이라서 고민했지만
공부를 하기위해 선택한 과정이니 선택과정도 진행했다
lv.4 요구사항도 보고가자
lv.4 요구사항
- AbstractOperation라는 추상화된 클래스를 만들기
- 기존에 구현한 AddOperation(더하기), SubtractOperation(빼기), MultiplyOperation(곱하기), DivideOperation(나누기) 클래스들과 관계를 맺고 Calculator 클래스의 내부 코드를 변경
- 스위프트의 어떤 문법을 이용하여 추상화할 수 있을지 생각해 봅시다
요구사항은 다음과 같았다
그냥 한마디로 추상화를 구현하라는 뜻.
간단히 추상화라는 개념에 대해서 살펴보자면
- 복잡한 시스템, 개체 또는 개념을 단순화하거나 일반화하는 과정
- 세부 사항을 숨기고 중요한 측면에만 초점을 맞춤으로써 문제를 해결하는 방식
라고 하는데 복잡성을 이해하기 쉬운 수준으로 단순화하는것 이라고 한다.
아무튼 swift에서는 이런 추상화를 주로 protocol
이라는 방식으로 추상화 하는것 같다.
그러나 나는 아직 1주차에서 클래스에 관한 개념만 배웠기에
protocol
방식은 사용하지 않았다.
바로 코드를 보자
먼저 Calculator
클래스다
class Calculator {
let addOp: AbstractOperation = AddOperation()
let subtractOp: AbstractOperation = SubtractOperation()
let multiplyOp: AbstractOperation = MultiplyOperation()
let divideOp: AbstractOperation = DivideOperation()
let remainderOp: AbstractOperation = RemainderOperation()
func add(firstNumber: Double, secondNumber: Double) -> Double {
return addOp.operate(firstNumber: firstNumber, secondNumber: secondNumber)
}
func subtract(firstNumber: Double, secondNumber: Double) -> Double {
return subtractOp.operate(firstNumber: firstNumber, secondNumber: secondNumber)
}
func multiply(firstNumber: Double, secondNumber: Double) -> Double {
return multiplyOp.operate(firstNumber: firstNumber, secondNumber: secondNumber)
}
func divide(firstNumber: Double, secondNumber: Double) -> Double? {
return divideOp.operate(firstNumber: firstNumber, secondNumber: secondNumber)
}
func remainder(firstNumber: Double, secondNumber: Double) -> Double {
return remainderOp.operate(firstNumber: firstNumber, secondNumber: secondNumber)
}
}
크게 변한것은 없고 바뀐 클래스명들에 맞게 인스턴스 선언 정도만 변경해줬다
다음은 추상화한 클래스와 연산 클래스들
class AbstractOperation {
func operate(firstNumber: Double, secondNumber: Double) -> Double {
return 0.0
}
}
class AddOperation: AbstractOperation {
override func operate(firstNumber: Double, secondNumber: Double) -> Double {
return firstNumber + secondNumber
}
}
class SubtractOperation: AbstractOperation {
override func operate(firstNumber: Double, secondNumber: Double) -> Double {
return Double(firstNumber - secondNumber)
}
}
class MultiplyOperation: AbstractOperation {
override func operate(firstNumber: Double, secondNumber: Double) -> Double {
return Double(firstNumber * secondNumber)
}
}
class DivideOperation: AbstractOperation {
override func operate(firstNumber: Double, secondNumber: Double) -> Double {
return firstNumber / secondNumber
}
}
class RemainderOperation: AbstractOperation {
override func operate(firstNumber: Double, secondNumber: Double) -> Double {
return firstNumber.truncatingRemainder(dividingBy: secondNumber)
}
}
AbstractOperation
이라는 추상화된 클래스를 만들어 주고
각 연산클래스가 해당 클래스를 상속하도록 작성했다.
상속한 뒤에 override
즉, 오버라이딩을 통하여 각 연산자에 맞게 operate
함수를 변경하여 사용했다
결과값도 잘 반환하는 걸 확인했다.
그 주에 배운 것들을 사용하는 과제를 했다는 것
물론 처음에는 좀 막막 했지만 차분히 진행하니 할 수 있었다
Class
관련 문제해결을 해본 것
아직 더 공부해야할 부분이 많아보이지만 실제로 기능을 구현하면서
사용해본 것
주어진 문제를 끝까지 해본 것
물론 난이도 상으로 엄청 어려운 과제는 아니었지만 그래도 선택과제까지 다 풀어본 것은 분명 의미가 있다
DivideOperation
의 옵셔널 변수 처리를 생각 못한 것
나눗셈 연산 특징상 nil
값이 나올 수 가 있는데 이에 대한 처리가 미흡했다는 점
chat gpt의 도움을 조금이라도 받은 점
가급적 혼자 문제를 해결하려고 했지만 조금이라도 도움을 받았다
알고보니 기본적인 부분을 한번 더 생각해보면 혼자서도 해결할 수 있었던거라 아쉽다.
여기까지 내가 풀이한 개인과제에 대한 설명과 좋았던 점, 아쉬웠던 점에 대해서 작성해봤다.
튜터님에게 이 과제에 대한 피드백도 받았는데 이에 대해서도 곧 작성해봐야겠다.