LSP?
리스코프 치환 원칙 - 자료형 S가 자료형 T의 하위형이라면 필요한 프로그램의 속성의 변경 없이
자료형 T의 객체를 자료형 S의 객체로 치환할 수 있어야 한다는 원칙
역시나 설명글은 너무나 어렵죠? 이젠 익숙하시죠 ㅎㅎ
다시 말해서, 상속을 설명하고 있습니다
부모객체와 자식객체가 있다고 가정할 때, 자식은 당연히 부모 객체로 치환할 수 있어야 합니다!
어려우니까 직사각형과 정사각형을 예로 들어볼게요
어렸을 때 수학을 배웠던 기억에 따르면, 정사각형은 직사각형이죠?
왜냐하면 정사각형은 직사각형의 성질을 그대로 가지고 있기 때문입니다!
그래서, 정사각형을 직사각형으로 표현할 수 있게 되는 것입니다!
그러면 바로 예시 코드로 넘어가볼까요~?
Code
우리는 도형이란 도메인을 지정하겠습니다.
거기에는 직사각형이라는 객체를 만들어볼게요~!
package solid.lsp;
public class Rectangle {
protected double width;
protected double height;
public double getWidth() {
return width;
}
public void setWidth(final double width) {
this.width = width;
}
public double getHeight() {
return height;
}
public void setHeight(final double height) {
this.height = height;
}
public double getArea() {
return width * height;
}
}
1. 직사각형 객체
보시면 아시겠지만, 너비(width)와 높이(height)를 필드로 가지는 객체입니다!
직사각형의 넓이(getArea)는 너비*높이 로 구할 수 있겠죠!
다음은, 정사각형을 만들어볼게요!
package solid.lsp;
public class Square extends Rectangle {
@Override
public void setWidth(final double width) {
this.height = width;
this.width = width;
}
@Override
public void setHeight(final double height) {
this.height = height;
this.width = height;
}
}
2. 정사각형 객체
정사각형은 너비와 높이가 같죠? ㅎㅎ
그래서 얼핏보면 참 올바른 Code인 것 같습니다.
그럼 검증을 해볼까요?
package solid.lsp;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
class SquareTest {
@Test
void 직사각형이_제대로_넓이를_구하는지_테스트() {
/* Given */
Rectangle rectangle = new Rectangle();
/* When */
rectangle.setHeight(4);
rectangle.setWidth(5);
/* Then */
assertThat(rectangle.getArea()).isEqualTo(20);
}
@Test
void 정사각형이_제대로_넓이를_구하는지_테스트() {
/* Given */
Rectangle rectangle = new Square();
/* When */
rectangle.setHeight(4);
rectangle.setWidth(5);
/* Then */
assertThat(rectangle.getArea()).isEqualTo(20);
}
}
3. Test Code
직사각형에 대한 Test Code와 정사각형에 대한 Test Code를 나타냈습니다!
우리는 앞서 설명한 LSP에 의해서, 자식 객체는 부모 객체의 역할을 포함해야 한다는 것을 지켜야합니다.
하지만, 결과는 어떨까요?
부모 객체(직사각형)의 넓이는 20을 나타내야 되지만,
자식객체(정사각형)의 넓이는 건방지게도 25를 나타내고 있습니다
이는 LSP를 위반한 것이 되겠습니다!
그럼 어떻게 해야 할까요?
여러 가지 방법이 있겠습니다만,
- getArea() 를 자식 클래스로 옮기는 방법
- 상속을 없애는 방법
와 같은 해결책이 있을 것 같습니다!
그러니까, LSP의 핵심은 자식 클래스가 항상 부모 클래스의 역할을 충실히 수행하는 것입니다!
참고
SOLID : Part3
'Developer > Kotlin & Java' 카테고리의 다른 글
SOLID - DIP(Dependency Inversion Principle)란 : 의존성 역전 원칙 (8) | 2019.11.27 |
---|---|
SOLID - ISP(Interface Segregation Principle)란? : 인터페이스 분리 원칙 (6) | 2019.11.26 |
SOLID - OCP(Open Closed Principle) : 개방 폐쇄 원칙 (0) | 2019.11.17 |
SOLID - SRP(Single Responsibility Principle) : 단일책임 원칙 (2) | 2019.11.17 |
[자바] 리플렉션 - Reflection (0) | 2019.04.11 |