SOLID - OOP design principle[3] - LSP
an object [such as a class] may be replaced by a sub-object [such as a class that extends the first class] without breaking the program.
Liskov substitution principle - Wikipedia
From Wikipedia, the free encyclopedia Object-oriented programming principle "Substitutability" redirects here. For the economic principle, see Substitute good. Liskov substitution was introduced by Barbara Liskov, photo taken in 2010. The Liskov substituti
en.wikipedia.org
위키피디아에서 위와 같이 설명하고 있다.
이는 풀어서 말하면 S가 T의 하위[자식] 자료형 이라면 프로그램 에러 없이 T의 객체를 S의 객체로 대체할 수 있어야 한다는 것이다.
예시를 통해서 알아보자.
open class KoreaChef {
open fun cook() {
println("한식을 요리하고 있습니다.")
}
}
class KoreaDesertChef: KoreaChef() {
override fun cook() {
println("약과를 만들고 있습니다.")
}
}
fun main() {
val chef = KoreaChef()
chef.cook()
}
KoreaChef은 KoreaDesertChef의 super class이고 main에서 위와 같은 작업을 하고 있다.
부모 클래스인 KoreaChef의 constructor 대신에 자식 클래스인 KoreaDesertChef의 constructor를 사용해도
잘 구동될 것이다. 즉, 위 예시는 LSP를 잘 준수하고 있다는 뜻이다.
그렇다면 위반하는 사례는 어떤 것일까?
open class KoreaChef {
open fun cook() {
println("한식을 요리하고 있습니다.")
}
open fun manageIngredient() {
println("재료 관리를 합니다.")
}
}
class KoreaDesertChef: KoreaChef() {
override fun cook() {
println("약과를 만들고 있습니다.")
}
}
class IngredientManager: KoreaChef() {
override fun cook() {
throw Exception()
}
override fun manageIngredient() {
println("재료 관리를 전문적으로 합니다.")
}
}
KoreaChef 클래스의 메서드로 manageIngredient를 추가해주고 자식 클래스로 IngredientManager을 만들어보자.
IngredientManager은 판매를 위한 음식을 조리할 수 없기에 에러를 던지도록 했다.
이때, 이전의 예시처럼 메인에서 KoreaChef()를 IngredientManger()으로 바꾸는 경우 에러가 발생할 것이다.
지금은 우리가 친숙한 단어와 상황으로 클래스를 작성해서 너무 당연하게 보이지만
결국은 어떤 상위 자료형의 자식 자료형을 설정할때 모든 기능에 대해서 치환이 적용될 수 있는지 고려하여 설정해야 한다는 것이다.

위 자료의 우측 벤다이어그램과 같은 관계를 가질 수 있도록 잘 설정해주는 것이 좋다.
그리고 이걸 준수하는 것이 바로 Liskov substitution principle[LSP]이다.