본문 바로가기

Java/객체지향

(OOP) 리스코프 치환 원칙

컴퓨터 프로그램에서 자료형 S가 자료형 T의 하위형이라면 필요한 프로그램의 속성(정확성, 수행하는 업무 등)의 변경 없이 자료형 T의 객체를 자료형 S의 객체로 교체(치환)할 수 있어야 한다는 원칙이다.

 

즉 상위 타입의 객체를 하위 타입으로 치환해도 상위 타입을 사용하는 객체는 정상적으로 동작되어야 함을 의미한다.

 

 

위반 사례

1. 명세에서 벗어난 값을 리턴한다.

2. 명세에서 벗어난 예외를 발생시킨다.

3. 명세에서 벗어난 기능을 수행한다.

  • 상위 타입에서 지정한 것 이외의 다른 기능을 하위 타입에서 사용하면 코드가 오동작할 수 있다.

코드 예시

직사각형을 부모로 갖는 정사각형에 대한 코드를 구현

 

높이와 넓이를 갖고 넓이를 구하는 직사각형

/**
 * Project : EffectiveStudy
 * Created by InteliJ IDE
 * Developer : junwoochoi
 * Date : 2020/02/20
 * Time : 8:23 오후
 */
class Rectangle {
    private  int width;
    private  int height;

    public void setWidth(int width) {
        this.width = width;
    }
    public void setHeight(int height) {
        this.height = height;
    }

    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return height;
    }

    public int area () {
        return this.height * this.width;
    }
}

직사각형을 상속하고 오버라이드 하는 정사각형

/**
 * Project : EffectiveStudy
 * Created by InteliJ IDE
 * Developer : junwoochoi
 * Date : 2020/02/20
 * Time : 8:26 오후
 */
public class Square extends Rectangle{
    private int width;
    private int height;

    @Override
    public void setWidth(int width) {
        this.width = width;
    }

    @Override
    public void setHeight(int height) {
        this.height = height;
    }
}

실행

public class Main {
    public static void main(String[] args) {
        boolean result1 = Main.checkArea(new Rectangle());
        boolean result2 = Main.checkArea(new Square());

        System.out.println(result1);
        System.out.println(result2);
    }
    static boolean checkArea (Rectangle rectangle) {
        rectangle.setHeight(5);
        rectangle.setWidth(4);

        return rectangle.area() == 20;
    }
}

 

실행결과

 

분명 같은 결과 값을 바랐지만 틀린 결과가 나왔다.

왜일까?

정사각형과 직사각형의 각각의 height, width 값을 출력한 결과 

정사각형은 5, 4 가 아닌 0인 것을 볼 수 있다.

 

 

이는 setWidth(), setHeight()로 쓸데없이 재정의 해버렸기 때문이다.

 

해결방법 super를 사용하면 된다.

@Override
public void setWidth(int width) {
    super.setWidth(width);
}

@Override
public void setHeight(int height) {
    super.setHeight(height);
}

 

결론은 

상위 클래스에서 정의한 것은 하위 클래스에서도 사용이 가능해야 한다는 점이다.
즉 자식 클래스는상위 클래스에서 정의한 모든 것을 수행 가능해야 한다.

상위 클래스에서는 하위 클래스의 공통적인 부분을 추상화하며 하위 클래스에서는 이를 구체화하는 방식으로 코드를 작성해보자.

 

 

 


References

https://jaepils.github.io/pattern/2018/07/04/liskov-substitution-principle.html

 

리스코프 치환 원칙 :: dev

리스코프 치환 원칙 04 Jul 2018 SOLID 객체지향원칙중에 하나인 리스코프 치환 원칙에 대해 알아보도록 하겠습니다. 바바라 리스코프라는 사람의 이름이 사용되다보니 쉽게 이해가 가지 않습니다. 정의 위키 백과에서 설명을 보면 다음과 같습니다. 컴퓨터 프로그램에서 자료형 S가 자료형 T의 하위형이라면 필요한 프로그램의 속성(정확성, 수행하는 업무 등)의 변경 없이 자료형 T의 객체를 자료형 S의 객체로 교체(치환)할 수 있어야 한다는 원칙이다. 영문

jaepils.github.io

https://dwenn.tistory.com/99

 

리스코프 치환 원칙(Liskov substitution principle, LSP)

리스코프 치환 원칙(Liskov substitution principle, LSP) Effective Java 를 보다가 접했는데, 검색해보니 객체지향 5대 원칙(SOLID) 중 하나라고 한다. 이것도 나중에 정리하기 위해 참고 링크를 걸어두어야 겠..

dwenn.tistory.com