본문으로 바로가기

[SOLID] 리스코프 치환의 법칙: LSP

category Computer/SOLID 2019. 7. 22. 15:15

LSP 원칙이란 ? Liskov Substitution Principle의 줄임말

 

- 서브타입(subtype)은 언제나 슈퍼타입(supertype)으로 교체할수 있어야 한다.

- 사용자는 파생 클래스에 대해 알 필요가 없다.

 

=> 즉 supertype이든 subtype이든 상관없이 작동해야 한다.

 

OCP vs LSP

 

OCP 

: abstraction , polymorphism ( inheritance ) 를 이용해서 구현

 

LSP

: OCP를 받쳐주는 polymorphism에 관한 원칙을 제공

 => subtype이나 supertype의 관계에서 서로 정확한 타입을 알 필요없이 프로그램이 돌아가야 한다.

 => sub클래스에서 super 클래스를 사용하면 안된다.

 

: LSP가 위반되면 OCP도 위반된다.

: LSP를 위반하게 되면 subtype이 추가될때마다 클라이언트들이 수정되어야 함

: instanceof / downcasting을 사용하는 것은 전형적인 LSP 위반의 징조

 

public class Rectangle {

	protected int width;
	protected int height;
	
	public Rectangle() {
	
	}

	public int getWidth() {
		return width;
	}

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

	public int getHeight() {
		return height;
	}

	public void setHeight(int height) {
		this.height = height;
	}
	
	public int area() {
		return this.width * this.height;
	}
	
}
public class Square extends Rectangle{

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

	@Override
	public void setHeight(int height) {
		this.width = height;
		this.height = height;
	}
	
}
public class Main {
	
	public static void main(String[] args) {
		System.out.println(testRectangle(new Square())); //true
		System.out.println(testRectangle(new Rectangle())); // false
	}
	
	static boolean testRectangle(Rectangle rectangle) {
		
		rectangle.setWidth(3);
		rectangle.setHeight(4);
		
		if( rectangle.area() != 12 ) {
			return false;
		}
		
		return true;
	}

}

 

부모인 Rectangle의 경우 true이지만 Square의 경우 false를 리턴하게 됩니다.

자식 클래스 Square의 경우 부모클래스 Rectangle의 기능을 제대로 수행하지 못하게 된다.

 

그러면 Square는 Rectangle의 맞을까라는 생각을 할수 있습니다.

 

The Representative Rule의 관점에서 생각을 해봐야한다고 합니다.

 

: 대리인은 자신이 대리하는 어떤 것들에 대한 관계까지 대리하지는 않는다.

  이혼 소송 변호사들(대리인)이 이혼하는 부부들의 관계(부부)를 대리(공유)하지 않는 것 처럼

  따라서 기하학에 따르면 Square IS-A Rectangle 이지만

  이들을 표현 / 대리 ( represent)하는 SW는 그들의 관계를 공유하지 않는다.

 

=> sw 관점에서 잘 생각해봐야한다.

 

또한,

다운캐스트, instanceof , 서브클래스에서 슈퍼클래스를 호출해야하는 상황이 온다면

상속 관계를 끊고 composition 관계로 만드는게 좋은것이 아닌가 생각해봐야함.