dev._.note

[Swift] 계산기 만들기 본문

Dev/SWIFT

[Swift] 계산기 만들기

Laena 2023. 12. 1. 19:40

과제 필수 구현 기능

  • Lv1 : 더하기, 빼기, 나누기, 곱하기 연산을 수행할 수 있는 Calculator 클래스를 만들고, 클래스를 이용하여 연산을 진행하고 출력하기
  • Lv2 : Lv1에서 만든 Calculator 클래스에 나머지 연산을 가능하도록 코드를 추가하고, 연산 진행 후 출력하기
  • Lv3 : AddOperation(더하기), SubstractOperation(빼기), MultiplyOperation(곱하기), DivideOperation(나누기) 연산 클래스를을 만든 후 클래스간의 관계를 고려하여 Calculator 클래스와 관계를 맺기
    • 관계를 맺은 후 필요하다면 Calculator 클래스의 내부코드를 변경하기
      • 나머지 연산자(%) 기능은 제외합니다.
    • Lv2 와 비교하여 어떠한 점이 개선 되었는지 스스로 생각해 봅니다.
      • hint. 클래스의 책임(단일책임원칙)

* 선택 구현 기능
Lv4 : AddOperation(더하기), SubtractOperation(빼기), MultiplyOperation(곱하기), DivideOperation(나누기) 연산 클래스들을 AbstractOperation라는 클래스명으로 만들어 사용하여 추상화하고 Calculator 클래스의 내부 코드를 변경합니다.
Lv3 와 비교해서 어떠한 점이 개선 되었는지 스스로 생각해 봅니다. (hint. 클래스간의 결합도, 의존성(의존성역전원칙))

구현코드 lv2

lv1은 여기서 나누기만 빼면됨

class Calculator {
    var firstNumber : Double
    var secondNumber : Double
    
    init(firstNumber: Double, secondNumber: Double) {
        self.firstNumber = firstNumber
        self.secondNumber = secondNumber
    }
    
    func calculate(simbol: String) -> Double {
        switch simbol {
        case "+" :
            return addResult()
        case "-" :
            return subtractResult()
        case "*" :
            return multiplyResult()
        case "/" :
            return divideResult()
        case "%" :
            return remainderResult()
        default :
            return 0
        }
    }
    
    func addResult() -> Double {
        firstNumber + secondNumber
    }
    
    func subtractResult() -> Double {
        firstNumber - secondNumber
    }
    
    func multiplyResult() -> Double {
        firstNumber * secondNumber
    }
    
    func divideResult() -> Double {
        firstNumber / secondNumber
    }
    
    func remainderResult() -> Double {
        Double(Int(firstNumber) % Int(secondNumber))
    }
}

let calculator = Calculator(firstNumber: 1, secondNumber: 3.5)
let addResult = calculator.calculate(simbol: "+")
let subtractResult = calculator.calculate(simbol: "-")
let multiplyResult = calculator.calculate(simbol: "*")
let divideResult = calculator.calculate(simbol: "/")
let remainderResult =  calculator.calculate(simbol: "%")

print("addResult : \(addResult)")
print("subtractResult : \(subtractResult)")
print("multiplyResult : \(multiplyResult)")
print("divideResult : \(divideResult)")
print("remainderResult : \(remainderResult)")

 

구현코드 lv3

import UIKit

class AddOperation {
    func operate(firstNumber: Int, secondNumber: Int) -> Double {
        return Double(firstNumber + secondNumber)
    }
}

class SubtractOperation {
    func operate(firstNumber: Int, secondNumber: Int) -> Double {
        return Double(firstNumber - secondNumber)
    }
}

class MultiplyOperation {
    func operate(firstNumber: Int, secondNumber: Int) -> Double {
        return Double(firstNumber * secondNumber)
    }
}

class DivideOperation {
    func operate(firstNumber: Int, secondNumber: Int) -> Double {
        return Double(firstNumber / secondNumber)
    }
}

class Calculator {
    private let addOperation: AddOperation
    private let subtractOperation: SubtractOperation
    private let multiplyOperation: MultiplyOperation
    private let divideOperation: DivideOperation
    
    init(addOperation: AddOperation, subtractOperation: SubtractOperation, multiplyOperation: MultiplyOperation, divideOperation: DivideOperation) {
        self.addOperation = addOperation
        self.subtractOperation = subtractOperation
        self.multiplyOperation = multiplyOperation
        self.divideOperation = divideOperation
    }
    
    func calculate(simbol: String, firstNumber: Int, secondNumber: Int) -> Double {
        switch simbol {
        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)
        default :
            return 0
        }
    }
    

}

let calculator = Calculator(
    addOperation: AddOperation(),
    subtractOperation: SubtractOperation(),
    multiplyOperation: MultiplyOperation(),
    divideOperation: DivideOperation()
)
let addResult = calculator.calculate(simbol: "+", firstNumber: 1, secondNumber: 290)
let subtractResult = calculator.calculate(simbol: "-", firstNumber: 43, secondNumber: 25)
let multiplyResult = calculator.calculate(simbol: "*", firstNumber: 523, secondNumber: 5)
let divideResult = calculator.calculate(simbol: "/", firstNumber: 98, secondNumber: 3)

print("addResult : \(addResult)")
print("subtractResult : \(subtractResult)")
print("multiplyResult : \(multiplyResult)")
print("divideResult : \(divideResult)")

 

  • 단일 책임 원칙이란 하나의 객체는 반드시 하나의 기능만을 수행하는 책임을 갖는다는 원칙.
  • 이는 클래스를 변경하는 이유는 오직 하나뿐이어야 한다는 것과 같은 의미로 객체가 담당하는 동작, 즉 책임이 많아질 수록 그 객체의 변경에 따른 영향도의 양과 범위가 매우 커지게 됨.

코드에 적용하면,

  • 책임 영역이 확실해져 한 책임의 변경에서 다른 책임의 변경의 연쇄작용에서 자유로울 수 있음. 즉, 코드의 의존성과 결합도를 줄일수있으므로 단일 책임 원칙은 특정 객체의 책임 의존성 과중을 지양하기 위한 중요하고 기본적인 원칙.
  • 가독성이 좋아지고 코드수정이 유리해짐.

구현코드 lv4

import UIKit
class AbstractOperation {
    func operate(firstNumber: Int, secondNumber: Int) -> Double{
        return 0
    }
}

class AddOperation : AbstractOperation {
    override func operate(firstNumber: Int, secondNumber: Int) -> Double {
        return Double(firstNumber + secondNumber)
    }
}

class SubtractOperation : AbstractOperation {
    override func operate(firstNumber: Int, secondNumber: Int) -> Double {
        return Double(firstNumber - secondNumber)
    }
}

class MultiplyOperation : AbstractOperation {
    override func operate(firstNumber: Int, secondNumber: Int) -> Double {
        return Double(firstNumber * secondNumber)
    }
}

class DivideOperation : AbstractOperation {
    override func operate(firstNumber: Int, secondNumber: Int) -> Double {
        return Double(firstNumber / secondNumber)
    }
}

class Calculator {
    private var abstractOperation : AbstractOperation
    
    init(operation: AbstractOperation) {
        self.abstractOperation = operation
    }
    
    func setOperation(operation: AbstractOperation) {
        self.abstractOperation = operation
    }
    
    func calculate(firstNumber: Int, secondNumber: Int) -> Double {
        abstractOperation.operate(firstNumber: firstNumber, secondNumber: secondNumber)
    }
}

let calculator = Calculator(operation: AddOperation())

let addResult = calculator.calculate(firstNumber: 1, secondNumber: 290)

calculator.setOperation(operation: SubtractOperation())
let subtractResult = calculator.calculate(firstNumber: 43, secondNumber: 25)

calculator.setOperation(operation: MultiplyOperation())
let multiplyResult = calculator.calculate(firstNumber: 523, secondNumber: 5)

calculator.setOperation(operation: DivideOperation())
let divideResult = calculator.calculate(firstNumber: 98, secondNumber: 3)

print("addResult : \(addResult)")
print("subtractResult : \(subtractResult)")
print("multiplyResult : \(multiplyResult)")
print("divideResult : \(divideResult)")
  • lv3 ➔ lv4 개선된점 연산이 늘어난다고해도 하나의 프로퍼티로 모든 연산이 가능해짐 
  • private var abstractOperation : AbstractOperation 
  • 의존성 역전 때문인데 즉, 객체는 구체적인 객체가 아닌 추상화에 의존해야 한다는 법칙
  • lv4는 풀이를 보고 작성하였음.

'Dev > SWIFT' 카테고리의 다른 글

[Swift] didSet 과 willSet  (0) 2023.12.04
[Swift] readLine()  (2) 2023.12.02
[Swift] 초기화(Initialization)  (1) 2023.11.30
[Swift] 상속(Inheritance)  (0) 2023.11.30
[Swift] Class와 Struct, Enum  (0) 2023.11.30