한 클래스는 하나의 책임만 가져야 한다
모든 클래스는 하나의 책임만 가지며, 클래스는 그 책임을 완전히 캡슐화해야 함
응집성 원칙에 근거하여 설명
소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다
프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다
특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다
추상화에 의존해야지, 구체화에 의존하면 안된다
의존성 주입
protocol에서 generic을 사용하는 방법
associatedtype 키워드 뒤에 사용할 TypePrameter를 붙여주면 됨
TypePrameter에게 프로토콜을 implement하고 싶을땐 콜론과 프로토콜을 붙여주면 됨
protocol CalculatorItemQueueProtocol {
associatedtype T: CalculateItem
func enqueue()
func dequeue() -> T?
}
implement한 타입에서 associatedtype을 typealias를 통해 타입을 명시해주는 것이 일반적
struct CalculatorItemQueue: CalculatorItemQueueProtocol {
typealias T = Any
private var linkedList = LinkedList<T>()
mutating func enqueue(_ element: T) {
linkedList.enqueue(element)
}
mutating func dequeue() -> T? {
return linkedList.dequeue()
}
}
typealias없이도 어떤 타입을 사용할 것인지 충분히 추론이 가능할 경우 typealias 생략 가능
struct CalculatorItemQueue: CalculatorItemQueueProtocol {
private var linkedList = LinkedList<Any>()
mutating func enqueue(_ element: Any) {
linkedList.enqueue(element)
}
mutating func dequeue() -> Any? {
return linkedList.dequeue()
}
}
기존 Generic Method 선언 방식을 그대로 사용하면 됨
protocol CalculatorItemQueueProtocol {
mutating func enqueue<T>(_ element: T)
mutating func dequeue<T>() -> T?
}
TypePrameter에게 제약을 주고 싶을땐 같은 방식 사용
protocol CalculatorItemQueueProtocol {
mutating func enqueue<T: CalculateItem>(_ element: T)
mutating func dequeue<T: CalculateItem>() -> T?
}
associatedtype과 함께 Generic Method를 사용하면 따로 논다
protocol CalculatorItemQueueProtocol {
associatedtype T
mutating func enqueue<V>(_ element: V)
mutating func dequeue<C>() -> C?
}