[OOP] SOLID 원칙 - LSP(리스코프치환원칙)

jxxn_a·2023년 11월 25일
0

TIL

목록 보기
27/28

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

  • 상위클래스의 객체가 사용하는 메서드는 하위클래스의 객체가 무엇인지 상관없이, 하위클래스의 객체도 사용할 수 있어야한다.
    => 상위클래스의 객체를 하위클래스의 객체로 치환해도 상위클래스를 사용하는 프로그램은 정상적으로 동작해야한다는 점이다.
  • 상위클래스의 특징은 그대로 갖고있으면서 + 되는 것이다.
  • 객체지향 프로그래밍의 특징 중 '상속','다형성'에 해당되는 것 같다.

💫 LSP 위반 예시

  • 수학적으로는 '정사각형이면 직사각형이다'라는 명제가 성립한다.

[ 클래스 설계 ]

open class Rectangle {
     open var width : Int = 1
     open var height : Int = 1
}

class square : Rectangle () {
   override var width : Int = super.width
           get() = super.width
           set(value) {
             field = value
             height = value
            }
                
                
   override var height : Int = super.height
           get() = super.height
           set(value) {
              field = value
              width = value
           }
}
  • 하지만, 직사각형 클래스에 폭보다 높이를 더 길게 만들어주는 기능이 필요하다면?
fun increaseHeight(rec : Retangle) {
   if(rec.height <= rec.width) {
     rec.height = rec.width + 10
   }
}
  • 위 함수를 Rectangle의 하위클래스인 square 클래스 객체가 사용한다면 높이가 더 길어지지 않는다. 이는 IncreaseHeight()함수가 Rectangle의 확장에 열려있지 않다는 뜻이다.
    => '정사각형은 직사각형이다.'라는 명제가 성립하지만, 프로그램을 짤 때 'square 객체는 Rectangle 객체이다.'로 설계하는 것은 문제가 있다.

  • 다형성에서 하위클래스는 인터페이스 규약을 다 지켜야한다.
    (예시) 자동차 인터페이스의 엑셀은 앞으로 가라는 기능이 있는데 갑자기 뒤로가게 한다면 LSP 위반이다. 느리더라도 앞으로 가야 LSP에 위반되지 않는다.


💫 LSP를 지키기 위해 지양해야할 점

  • 상위클래스의 명세를 벗어나는 것(Down Casting)
    => 코드적으로는 문제없지만, 추상화한 타입을 그 하위 타입의 객체로 변환했을 때 예상한대로 동작하지 않는다는 것을 방지하는 것이 LSP 원칙을 지키는 이유이다.

🪐 하위 타입을 정의할 때는 상위 타입의 명세를 지켜야 LSP를 지킬 수 있다. 따라서 상위 타입에 명세를 명확하게 잘 기록해야한다.

🪐 DownCasting을 사용하면 OCP를 위반하기도 하지만, LSP를 위반하기도 한다.상위 타입 객체를 하위 타입의 객체로 바꿨을 때 모든 하위 타입에 대해 잘 동작하지 않을 가능성이 크기 때문이다. 상위 타입의 객체가 하위타입인지 확인하는 코드를 사용하는 것은 상위 클래스가 제대로 추상화 되지 않았다는 것을 의미한다.


참고한 블로그

0개의 댓글