title: **"**LSP : The Liskov Substitution Principle**"**
description: "LSP : The Liskov Substitution Principle"
cleanUrl: /sw-engineer/lsp
floatFirstTOC: right
**public class Line** {
public Line(Point p1, Point p2){ /*code*/} }
public Point P1 { get { /*code*/} } }
public Point P2 { get { /*code*/} } }
public virtual bool IsOn(Point p) {/*code*/}
}
**public class LineSegment : Line** {
public LineSegment(Point p1, Point p2)
: base(p1, p2) {}
public double Length() { get {/*code*/} }
//Line.IsOn()의 참이 아래에서는 거짓이 될 수 있음.
public override bool IsOn(Point p) {/*code*/}
}
**class LineClient** {
void DoSomething(Line) { /*code*/ }
}
LineClient.DoSomething()
은 해당 매개변수(line) 위의 모든 점에서 IsOn() == true
를 기대하고 코드 작성 가능.
LineSegment
instance를 **LineClient.DoSomething()
**의 매개변수로 넘길 경우, **IsOn() == false
**가 가능함으로 **LineClient.DoSomething()
**은 유효하지 않은 코드가 됨.**public abstract class LinearObject** {
public LinearObject(Point p1, Point p2) { /*code*/} }
public Point P1 { get { /*code*/} } }
public Point P2 { get { /*code*/} } }
public abstract virtual bool IsOn(Point p);
}
**public class Line : LinearObject** {
public Line(Point p1, Point p2) : base(p1, p2) {}
public override bool IsOn(Point p) {/*code*/}
}
**public class LineSegment : LinearObject** {
public LineSegment(Point p1, Point p2) : base(p1, p2) {}
public double GetLength() {/*code*/}
public override bool IsOn(Point p) {/*code*/}
}
**class LineClient** {
void DoSomething(Line) { /*code*/ }
}
LineClient.DoSomething()은 더 이상 잠재적 버그를 갖지 않음
일반적으로 factoring을 통한 공통의 상위 클래스는 abstract가 될 가능성이 높고, 해당 상위 클래스는 언젠가 그 자체만의 client code를 갖기 마련.