좋은 설계란 기본적으로 시스템에 새로운 요구사항이나 변경이 있을 때 가능한 한 영향 받는 부분을 최소화한 설계이다.
가장 대표적인 예제로는 직사각형 정사각형 문제가 있다.
IS-A 관계를 따져보았을때, 정사각형은 직사각형이지만 직사각형은 정사각형이 아니다.
//MARK: LSP 위배
/*
리스코프 위배
부모타입인 Rectangle에서 자식인 Square로 변경시 너비 구하는 식 달라짐
정사각형은 직사각형이다.
직사각형은 정사각형이 아니다.
*/
class Rectangle {
let width: Int
let height: Int
func area() -> Int {
return width * height
}
init(width: Int, height: Int) {
self.width = width
self.height = height
}
}
class Square: Rectangle {
override func area() -> Int {
return width * width
}
}
let r = Rectangle(width: 5, height: 4) //20
r.area()
let r2 = Square(width: 5, height: 4) //25
r2.area()
//: [Next](@next)
//만약 부모클래스 기능을 재정의 하게 되면 OCP 위배될수도
//MARK: LSP
protocol Shape {
func area() -> Int
}
class LSPRectangle: Shape {
private let width: Int
private let height: Int
func area() -> Int {
return width * height
}
init(width: Int, height: Int) {
self.width = width
self.height = height
}
}
class LSPSquare: Shape {
private let width: Int
func area() -> Int {
return width * width
}
init(width: Int) {
self.width = width
}
}
위의 코드와 가이 Shpae protocol을 통해 area를 구하는 함수를 정의해줄 수 있다.
이렇게 LSP를 준수하면 추상화 된 것으로부터 상속된 다른 클래스를 공통적으로 작성해 줄 수 있다.
이렇게 되면 OCP도 자연스럽게 지켜줄수 있다.