Definition

Programs that references an object from a base class must be able to use an object of a derived class without behavior differences and without knowing about its existence.

Base와 Base를 상속받는 객체가 있을 때, 특정 프로그램에서 Base를 받아와 사용한다면, Base를 사용하든, 상속받은 객체를 사용하든, 차이점이 없어야 하고, 차이점이 보여서도 안된다.

예시1 - Unexpected Behaviors

class Rectangle {
    var width: Int
    var height: Int

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

    func area() -> Int {
        return width * height
    }
}

class Square: Rectangle {
    override var width: Int {
        didSet {
            super.height = width
        }
    }

    override var height: Int {
        didSet {
            super.width = height
        }
    }
}
func main() {
    let square = Square(width: 10, height: 10)

    let rectangle: Rectangle = square

    rectangle.height = 7
    rectangle.width = 5

    print(rectangle.area()) 
    // As a rectangle we should expect the area as 7 x 5 = 35, but we got 5 x 5 = 25
}

main()에서 Rectangle 타입으로 두고 rectangle 변수에 Square 타입 값을 할당하면 최종적으로 print 되는 값은 25가 됨

이 상황에서는, Square를 Rectangle 타입에 할당했지만, rectangle.height = 7 과 같은 코드는 Square에서 동작하는 것과 동일하게 동작

즉, Rectangle 타입으로 적어뒀고, 그렇게 알고 있는데, Square로 동작한다는 점에서 LSP를 위반함

LSP를 따르지 않았을 때 생기는 문제

추상화를 하기 위해 보통 Polymorphism(다형성)에 도움을 받음 (e.g. 마켓 앱에서 살 수 있는 모든 제품을 API로 받아올 때 다양한 아이템들을 추상화해서 받기)

위 예시에서 rectangle 이라는 변수가 어떤 타입이 될 수 있는지 모름 정사각형인지, 직사각형인지 등등 …

그렇기 때문에 우리는 rectangle 처럼 동작할 것이라고 예상할 수 있음 하지만, 위 예시에서 실상은 rectangle 로 동작하지 않고, square 로 동작함

LSP를 따르게 된다면