내일배움캠프 앱개발 iOS 트랙 본캠프 2주차
Today I Learned
Class 추상화
swift에는 직접적인 추상 클래스 개념이 없지만 프로토콜 Protocol과 클래스 상속을 통해서 추상화를 구현할 수 있다!
자식 클래스에서 반드시 오버라이딩해야만 사용할 수 있다. 즉!! 기본적인 행동을 정의하고 그 행동을 수행하는 것은 (코드 내부를 구현하는 것) 상속받을 하위 클래스에게 맡긴다.
추상화를 사용하는 이유
- 코드 간결 -> 코드가 복잡해지는 걸 방지하고 이해하기 쉬운 코드를 작성할 수 있다.
- 타입 안정 -> 런타임 오류 가능성을 줄여준다.
- 확장 -> 새로운 기능을 추가하기가 쉬워진다! 기존 클래스는 수정하지 않고, 새로운 클래스를 추가/확장하는 방식으로 만들 수 있다.
Calculator.swift 파일 분리
기존에는 계산을 위한 클래스가 전부 ViewController.swift 파일에 들어있었다.
그러나 ViewController에는 말 그대로 UI 만을 위한 코드가 있는게 좋다고 튜터님께 피드백을 받아서 파일을 분리해주었다.
※ 참고!
swift는 class를 사용하기 위해서 다시 import 해 줄 필요가 없습니다.
따라서, 파일을 분리해도 viewController에서 import 하지 않고 바로 사용 가능합니다.
// MARK: - Class Calculator
class Calculator {
private var abstractOperation: AbstractOperation
init(abstractOperation: AbstractOperation) {
self.abstractOperation = abstractOperation
}
func setOperation(operation: AbstractOperation) {
self.abstractOperation = operation
}
func calculate(_ numbers: [Double], _ operatorType: String) -> Double {
abstractOperation.operate(numbers)
}
}
// MARK: - AbstractOperation Override
class AbstractOperation {
func operate(_ numbers:[Double]) -> Double {
return 0
}
}
class AddOperation: AbstractOperation {
override func operate(_ numbers: [Double]) -> Double {
return numbers[0] + numbers[1]
}
}
class SubtractOperation: AbstractOperation {
override func operate(_ numbers: [Double]) -> Double {
return numbers[0] - numbers[1]
}
}
class MultiplyOperation: AbstractOperation {
override func operate(_ numbers:[Double]) -> Double {
return numbers[0] * numbers[1]
}
}
class DivideOperation: AbstractOperation {
override func operate(_ numbers:[Double]) -> Double {
return numbers[0] / numbers[1]
}
}
외부에서 주입받는 형태로 추상화 클래스를 만들었다.
위 코드에서는
private var abstractOperation: AbstractOperation
init(abstractOperation: AbstractOperation) {
self.abstractOperation = abstractOperation
}
이 두 부분을 통해 사용할 Class 를 받아와서 지정한다.
func calculate(_ numbers: [Double], _ operatorType: String) -> Double {
abstractOperation.operate(numbers)
}
실질적으로 계산을 위해 사용하는 함수는 이쪽이다.
var calculatorAdd = Calculator(abstractOperation: AddOperation())
.
.
.
calculatorAdd.calculate(numberValue, type)
ViewController.swift 안에서는 이런 식으로 활용했다.
의존성 주입
Dependency 의존성
서로 다른 객체 사이에 의존 관계가 있다는 것
즉, 의존하는 객체가 수정되면, 다른 객체도 영향을 받는다는 것이다.
import UIKit
struct Eat {
func coffee() {
print("아메리카노")
}
func meal() {
print("피자")
}
}
struct Person {
var todayEat: Eat
func coffee() {
todayEat.coffee()
}
func meal() {
todayEat.meal()
}
}
Person 클래스는 Eat 클래스에 의존한다.
의존성이 커지면, 재활용성이 크게 떨어지고 매번 의존하는 클래스의 내용을 수정해주어야 한다는 단점이 있다.
Injection 주입
외부에서 객체를 생성해서 넣는 것
class Eat:Menu {
var coffee: String
var meal: String
init(coffee: String, meal: String) {
self.coffee = coffee
self.meal = meal
}
func printCoffee() {
print("아메리카노")
}
func printMeal() {
print("피자")
}
}
let menu = Eat(coffee: "아메리카노", meal: "피자")
생성자를 사용해서 외부에서 값을 주입할 수 있다.
의존성 주입을 하는 이유?
- Unit Test가 용이해진다.
- 코드의 재활용성을 높여준다.
- 객체 간의 의존성(종속성)을 줄이거나 없엘 수 있다.
- 객체 간의 결합도를 낮추면서 유연한 코드를 작성할 수 있다.
의존 관계 역전 법칙 Dependency Inversion Principle
구체적인 객체는 추상화된 객체에 의존해야 한다
1. 추상적인 객체를 만든다
class AbstractOperation {
func operate(_ numbers:[Double]) -> Double {
return 0
}
}
2. setOperation 함수를 이용해서 의존성주입을 시킨다.
class Calculator {
private var abstractOperation: AbstractOperation
init(abstractOperation: AbstractOperation) {
self.abstractOperation = abstractOperation
}
func setOperation(operation: AbstractOperation) {
self.abstractOperation = operation
}
func calculate(_ numbers: [Double], _ operatorType: String) -> Double {
abstractOperation.operate(numbers)
}
}
'TIL' 카테고리의 다른 글
[TIL] 2023.12.05 | 키오스크(2/n) 데이터 모델링 (0) | 2023.12.05 |
---|---|
[TIL] 2023.12.04 | 키오스크(1/n) 열거형과 구조체의 사용법 차이, CaseIterable (0) | 2023.12.04 |
[TIL] 2023.11.30 | 계산기(3/n) 클래스 단일책임원칙, OCP (0) | 2023.11.30 |
[TIL] 2023.11.29 | 계산기(2/n) 숫자 2개 이상을 계산할 수 있는 사칙연산 구현하기 (1) | 2023.11.29 |
[TIL] 2023.11.28 | [계산기 (1/n)]storyboard UIButton UILabel 사용, Swift 사칙연산 구현하기 (0) | 2023.11.28 |