객체지향 5원칙(SOLID) - 리스코프 치환 원칙

2022. 2. 17. 16:40PHP

객체지향 5원칙

올바른 객체지향 설계를 위해 수립한 원칙이 있으며, 이 다섯 가지의 원칙을 통틀어 객체지향 5원칙(SOLID)이라 명명한다. 필수로 적용하지 않지만, 적어도 이 규칙을 준수하면 준수할 수록 올바르게 설계된 객체지향이라 할 수 있습니다.

 

이 다섯 가지 원칙은 아래와 같습니다.

1. 단일 책임 원칙 (Single Responsibility Principle)

2. 개방 폐쇄 원칙 (Open-Closed Principle)

3. 리스코프 치환 원칙 (Liskov Substitution Principle)

4. 인터페이스 분리 원칙 (Interface Segregation Principle)

5. 의존성 역전 원칙 (Dependency Inversion Principle)

 

각 원칙의 영어 앞글자를 따서 SOLID원칙이라고 합니다.

리스코프 치환 원칙 (Liskov Substitution Principle)

리스코프 치환 원칙은 상위 타입의 객체를 하위 타입의 객체로 치환해도 상위 타입을 사용하는 프로그램은 정상적으로 동작해야 한다라는 원칙입니다. 

간단한 코드로 예시를 구현해보겠습니다.(PHP)

상황)

이 원칙에 가장 많이 등장하는 정사각형/직사각형을 예제로 사용해보겠습니다.

 

리스코프 치환 원칙을 지키지 않은 코드

<?php

class Rectangle
{
    protected $_WIDTH;
    protected $_HEIGHT;

    public function setWidth($width)
    {
        return $this->_WIDTH = $width;
    }

    public function setHeight($height)
    {
        return $this->_HEIGHT = $height;
    }

    public function getArea()
    {
        return $this->_WIDTH * $this->_HEIGHT;
    }
}
class Square extends Rectangle
{
    public function setWidth($width)
    {
        $this->_WIDTH = $width;
        $this->_HEIGHT = $width;
    }

    public function setHeight($height)
    {
        $this->_WIDTH = $height;
        $this->_HEIGHT = $height;
    }
}
$rec = new Rectangle();
$rec->setWidth(3);
$rec->setHeight(4);
var_dump($rec->getArea() == 12); // true

$squ = new Square();
$squ->setWidth(3);
$squ->setHeight(4);
var_dump($squ->getArea() == 12); // false
?>

 

논리상으로 정사각형은 직사각형이지만, 직사각형은 정사각형이 아닙니다. 위 코드와 SOLID 법칙의 기준으로 보았을 때 상속 관계로 존재할 수 없다는 것을 알아 보았습니다. 정사각형이 직사각형을 상속하는 관계가 아닌 도형을 상속하도록 리팩토링 해보겠습니다.

 

<?php

interface Shape
{
    public function getArea();
}

class Rectangle implements Shape
{
    protected $_WIDTH;
    protected $_HEIGHT;

    public function __construct($width,$height)
    {
        $this->_WIDTH=$width;
        $this->_HEIGHT=$height;
    }

    public function getArea()
    {
        return $this->_WIDTH * $this->_HEIGHT;
    }
}
class Square extends Rectangle
{
    public function __construct($width)
    {
        $this->_WIDTH=$width;
    }

    public function getArea()
    {
        return $this->_WIDTH * $this->_WIDTH;
    }

}
$rec = new Rectangle(3,4);
var_dump($rec->getArea() == 12); // true

$squ = new Square(3);
var_dump($squ->getArea() == 9); // true
?>

 

요약

이제 둘의 상속 관계가 없어졌기 때문에 리스코프 치환 원칙을 위반하지 않는 코드가 되었습니다.

결과적으로 리스코프 치환 원칙은 베이스 클래스가 서브 클래스로 치환되어도 동일한 동작을 보장해야 한다는 원칙입니다. 이 원칙을 지켰을 경우 자동적으로 개방-폐쇄 원칙을 위반 하지 않게 한다고도 합니다.

 

참고자료

자바를 예시로 든 자료 https://steady-coding.tistory.com/383

 

[SOLID] 리스코프 치환 원칙(LSP)이란?

안녕하세요? 제이온입니다. 저번 시간에는 개방 폐쇄 원칙에 대해서 알아 보았습니다. 오늘은 리스코프 치환 원칙을 설명하겠습니다. 리스코프 치환 원칙 (Liskov Substitution Principle)의 정의 리스코

steady-coding.tistory.com

typescript를 예시로 든 자료 https://medium.com/humanscape-tech/solid-%EB%B2%95%EC%B9%99-%E4%B8%AD-lid-fb9b89e383ef