■ LSP
- 부모 객체와 자식 객체가 있을 때 부모 객체를 호출하는 동작에서 자식 객체가 부모 객체를 완전히 대체할 수 있다는 원칙
- 자식 클래스는 부모 클래스가 정의한 계약을 위반하지 않고 부모 클래스의 기능을 확장하거나 수정할 수 있어야 한다

■ LSP 위반한 예제
// 부모 클래스
class Bird {
public void fly() {
System.out.println("새는 날 수 있다.");
}
}
// 자식 클래스
class chicken extends Bird {
@Override
public void fly() {
throw new ChickenException("닭은 날지 못한다.");
}
}
// 테스트 클래스
public class LSPViolationTest {
public static void main(String[] args) {
Bird bird = new Chicken();
bird.fly(); // 예외 발생: 닭은 날지 못한다.
}
}
- Bird 클래스의 fly() 메서드는 모든 새들이 날 수 있따는 가정 하에 동작하는 메서드
- Chicken은 날 수 없지만, Bird 클래스를 상속받고 fly() 메서드를 오버라이드하면서 예외를 던진다.
- Bird 타입의 객체로 Chicken 객체를 대체하려 할 때 예외가 발생하고, 이는 LSP 원칙에 어긋난다.
- Chicken는 Bird 가 기대하는 fly() 동작을 제대로 구현하지 않고 예외를 던지기 때문에 대체할 수 없는 객체
■ LSP 준수한 예제
// 부모 클래스
class Bird {
public void eat() {
System.out.println("새는 먹는 중이다.");
}
}
// 날 수 있는 새 클래스
class FlyingBird extends Bird {
public void fly() {
System.out.println("날 수 있는 새는 날고있다.");
}
}
// 날 수 없는 새 클래스
class Chicken extends Bird {
// 닭은 날 수 없으므로 fly() 메서드를 제공하지 않음
public void run() {
System.out.println("닭은 뛰는 중이다.");
}
}
// 테스트 클래스
public class Main {
public static void main(String[] args) {
// FlyingBird 객체
Bird bird1 = new FlyingBird();
bird1.eat();
((FlyingBird) bird1).fly(); // FlyingBird는 날 수 있음
// Chicken 객체
Bird bird2 = new Chicken();
bird2.eat();
((Chicken) bird2).run(); // 닭은 날 수 없고, 대신 달릴 수 있음
}
}
- Chicken는 Bird 클래스를 상속 받지만, fly() 메서드를 제공하지 않고 자신의 특성에 맞는 run() 메서드를 제공한다.
- Chicken는 Bird 클래스를 대체할 수 있지만, 날 수 없는 새로서 제대로 기능 수행
- FlyingBird는 날 수 있는 새들을 다루기 때문에 fly() 메서드를 제공하며 날 수 있는 새들이 Brid 객체로 다뤄져도 문제 발생 안함
- Chicken는 fly() 메서드를 호출하지 않으며 run() 메서드를 호출한다. 각 객체는 자신에게 맞는 기능만 수행
'JAVA' 카테고리의 다른 글
[JAVA] DIP (의존 관계 역전 원칙) (0) | 2025.04.12 |
---|---|
[JAVA] ISP (인터페이스 분리 원칙) (0) | 2025.04.08 |
[JAVA] SRP (단일 책임 원칙) (0) | 2025.04.06 |
[JAVA] OCP (개방 폐쇄 원칙) (0) | 2025.04.06 |
[JAVA] 다형성(2) - abstract, 인터페이스 (0) | 2025.03.30 |