우아한테크코스/level1

리스코프 치환원칙

무비인 2022. 3. 19. 21:44

리스코프 치환원칙은 상속에 대해 공부하다가 알게 되었다.

개념

부모 클래스의 인스턴스를 사용하는 위치에 자식 클래스의 인스턴스를 대신 사용했을 때,

코드가 원래 의도대로 작동해야한다.

리모컨 예제

1
2
3
4
5
6
7
8
9
10
11
12
13
 class 리모컨 {
 
    boolean power;
 
    void 켜기(){
        power = true;
    }
 
    void 끄기(){
        power = false;
    }
 
}
cs

 

이제 이걸 상속받은 TV 리모컨, 에어컨 리모컨 이 있다고 하자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 class Tv_리모컨  extends 리모컨 {
 
    boolean power;
 
    void 켜기(){
        power = true;
    }
 
    void 끄기(){
        power = false;
    }
 
    void 채널 돌리기(){}
 
}
cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 class 에어컨_리모컨 extends 리모컨 {
 
    boolean power;
 
    void 켜기(){
        power = true;
    }
 
    void 끄기(){
        power = false;
    }
 
    void 온도_올리기(){}
 
 
    void 온도_낮추기(){}
}
cs

 

위 두개는 부모 클래스인 리모컨이 제공하는 기능을 제공하면서 추가로 다른 기능을 제공하고 있다.
따라서 리스코프 치환원칙을 잘 지켰다고 할 수 있다.

못 지켰을 때는 언제일까?


자식 클래스에서 잘못된 오버라이딩을 할 때

현재 메서드 명만 봤을 때 에어컨의 리모컨은 기계의 전원을 켜고, 끄는 것 처럼 보인다.
그런데 실제동작은 켜기를 눌렀을 때 꺼지고, 꺼짐을 눌렀을 때 켜지도록 오버라이딩 되었다.
이는 부모 클래스가 의도한 기능을 제공했다고 볼 수 없기 때문에 리스코프 치환원칙에 위배 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 class 에어컨_리모컨 extends 리모컨 {
 
     boolean power;
    int 온도;
 
    @Override
    void 켜기(){
        power = false
    }
 
    @Override
    void 끄기(){
        power = true;
    }
 
    void 온도 올리기(){
        온도 = 온도+1;
    }
 
    void 온도 낮추기(){
        온도 = 온도-1;
    }
}
cs

자식 클래스에서 추가된 변수를 사용하여 오버라이딩을 할 때

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 class 에어컨_리모컨 extends 리모컨 {
 
     boolean power;
    int 온도;
 
    @Override
    void 켜기(){
        power = false;
        온도 = 10;
    }
 
    @Override
    void 끄기(){
        power = true;
        온도 = 0;
    }
 
    void 온도 올리기(){
        온도 = 온도+1;
    }
 
    void 온도 낮추기(){
        온도 = 온도-1;
    }
}
cs

 

왜 리스코프 치환원칙을 지켜야하는가?

1) 유지보수성을 위해

리스코프 치환원칙을 위배한다고 해서 시스템 상 에러가 발생하지 않는다.

그래서 더 위험하다. 프로그램 작성자가 다른 사람이 위 켜기 메서드를 볼 때

켜기를 눌렀는데 온도가 조절 될 것이라 생각이 들겠는가? 

따라서 이상 동작이 어디서 시작 된 것인지 파악하기 어려워진다. 의도 된 동작만 하게끔 리스코프 치환원칙을 지키자.