Skip to main content

LSP 원칙

· 3 min read

LSP(Liskov Substitution Principle) - 리스코프 치환 원칙

  • 부모(super class)로 동작하는 곳에서 자식(sub class)를 넣어주어도 대체가 가능해야 한다는 원칙
  • 자식 클래스를 구현할 때, 기본적으로 부모 클래스의 기능이나 능력들을 물려받는데 여기서 자식 클래스가 동작할 때, 부모 클래스의 기능들을 제한하면 안된다는 뜻
  • 상속을 할 때 완전한 상속이 아닌 경우는 Interface로 구현하는 것이 맞다(Refactoring 책에서도 나옴)
    • 자바의 stack이 부모의 기능을 모두 사용하지도 않으면서 array 상속받아 사용
  • 부모 클래스의 타입에 자식 클래스의 인스턴스를 넣어도 똑같이 동작하여야 한다

BadCase

class RectangleBad {
var width: Float = 0
var height: Float = 0

var area: Float {
return width * height
}
}

class SquareBad: RectangleBad {
override var width: Float {
didSet {
height = width
}
}
}

func printArea(of rectangle: RectangleBad) {
rectangle.height = 3
rectangle.width = 6
print(rectangle.area)
}

let rectangle = RectangleBad()
printArea(of: rectangle)

let square = SquareBad()
printArea(of: square)
  • Rectangle(부모) 클래스를 상속받은 Square(자식) 클래스에서 부모의 모든 자원을 활용하지 못하는 형태라 LSP에 어긋나게 된다.
  • 부모의 역할을 자신이 온전하게 대체하지 못함

NiceCase

protocol Shape  {
var area: Float { get }
}

class RectangleNice: Shape {
private let width: Float
private let height: Float

var area: Float {
return width * height
}

init(width: Float, height: Float) {
self.width = width
self.height = height
}
}

class SquareNice: Shape {
private let length: Float

var area: Float {
return self.length * self.length
}

init(length: Float) {
self.length = length
}
}

let rectangleNice = RectangleNice(width: 3, height: 6)
let squareNice = SquareNice(length: 6)
  • Protocol을 사용하여 area 함수를 구현하게 만들어 Rectangle, Square 각각이 area 함수를 구현한다
  • 구현부는 채택하는 하위 클래스로 넘기면 LSP의 원칙에 어긋나지 않는다

참조