LSP(Liskov Substitution Principle)이란?
상위 타입의 객체를 하위 타입의 객체로 치환하여 사용하여도 프로그램은 정상적으로 동작해야 한다.
LSP(Liskov Substitution Principle)은 상속이 이루어진 클래스간에 상위 타입에 하위 타입의 객체를 치환하여 사용할 때에도 프로그램의 안정성이 보장되어야 한다는 것을 뜻한다. 객체지향 프로그래밍을 해왔던 개발자에겐 너무도 당연하게 스며들어 있는 개념이다
예시
클래스 상속 구조
아래와 같이 Person, ChildA, ChildB를 정의한다. ChildA와 ChildB는 Person을 상속받고 Person의 GetName 함수를 Override하고 있다.
public class Parent
{
public virtual string GetName() => nameof(Parent);
}
public class ChildA : Parent
{
public override string GetName() => nameof(ChildA);
}
public class ChildB : Parent
{
public override string GetName() => nameof(ChildB);
}
실행
먼저, Person이라는 Parent 형식의 개체를 생성하고 GetName 함수를 호출한다.
그 이후 Person 변수에 ChildA를 생성하여 할당하고 GetName 함수를 호출한다.
ChildB도 ChildA와 마찬가지로 작성한다.
var person = new Parent();
Console.WriteLine(person.GetName());
person = new ChildA();
Console.WriteLine(person.GetName());
person = new ChildB();
Console.WriteLine(person.GetName());
Console.ReadLine();
결과
위 실행 코드의 결과는 아래와 같다. 최초에 Parent 형식으로 생성된 객체에 그 하위 객체인 ChildA와 ChildB를 할당하여 같은 메서드를 호출했을 때 각각 결과가 다르게 호출되는 것을 확인할 수 있다.
예외의 경우
위 예시를 보면 너무도 당연하게 LSP 원칙을 지키고 있었다고 생각하지만 예외의 경우가 있다. 직사각형, 정사각형이 그 대표적인 예시이다. 누구나 알고 있듯이 정사각형은 직사각형이지만 직사각형은 정사각형이 아니다. 이를 객체에 대입시켜 생각하면 어떨까?
위와 같이 Rectangle, Square를 정의했다. 두 객체 모두 가로와 세로 사이즈를 증가시키는 ScaleHeight, ScaleWidth 함수를 가지고 있다. 하지만 Square의 경우는 정사각형을 뜻하므로 ScaleHeight, ScaleWidth 함수는 Width, Height 모두를 증가시킨다.
public class Rectangle
{
public int Width { get; set; }
public int Height { get; set; }
public Rectangle(int width, int height)
{
Width = width;
Height = height;
}
public virtual void ScaleHeight(int scale)
{
Height++;
}
public virtual void ScaleWidth(int scale)
{
Width++;
}
public override string ToString() => $"w : {Width}, h : {Height}";
}
public class Square : Rectangle
{
public Square(int size) : base(size, size)
{
}
public override void ScaleHeight(int scale)
{
Width ++;
Heigth ++;
}
public override void ScaleWidth(int scale)
{
Width ++;
Heigth ++;
}
}
Rectangle, Squre를 위의 LSP 예시와 동일하게 실행시켜보았다. 이때 Square 객체의 ScaleHeight 함수를 호출한 뒤 가로 세로 값을 확인해보면 Width, Height가 모두 증가해 있는 것을 확인할 수 있다.
var rect = new Rectangle(10, 10);
Console.WriteLine("Rect (10, 10)");
Console.WriteLine(rect.ToString());
rect.ScaleHeight(10);
Console.WriteLine("Rect Scaled (10)");
Console.WriteLine(rect.ToString());
rect = new Square(10);
Console.WriteLine("Square (10)");
Console.WriteLine(rect.ToString());
rect.ScaleHeight(10);
Console.WriteLine("Square Scaled (10)");
Console.WriteLine(rect.ToString());
Console.ReadLine();
위 처럼 설계를 진행한다면 Rectangle의 ScaleHeight, ScaleWidth 함수의 의미가 Square에서는 전혀 다르게 동작되므로 LSP 원칙에 어긋나 프로그램이 정상적으로 동작하지 않을 수 있다.
'Software Develop > 개발이론' 카테고리의 다른 글
SOLID원칙 - ISP(Interface Segregation Principle) (0) | 2023.01.16 |
---|---|
SOLID원칙 - SRP (Single Responsibility Principle) (0) | 2023.01.16 |
SOLID원칙 - OCP (Open Closed Principle) (0) | 2023.01.16 |
의존성 주입 (Dependency Injection) (2) | 2023.01.13 |