상위 클래스가 조금만 잘못 변경되어도 다른 하위 클래스가 잘못 동작하게 될 수 있음
위와 같이 상속을 사용하면서 하위 클래스가 증가하게 되어, 복잡도가 증가하게 됨
public class Container extends ArrayList<Luggage> {
private int maxSize;
private int currentSize;
public Container(int maxSize){
this.maxSize = maxSize;
}
public void put(Luggate lug) throws NotEnoughSpaceException {
if(!canContain(lug)) throw new NotEnoughSpaceException();
super.add(lug);
currentSize += lug.size();
}
public void extract(Luggage lug){
super.remove(lug);
this.currentSize -= lug.size();
}
public boolean canContain(Luggage lug){
return maxSize >= currentSize + lug.size();
}
}
위 Container
클래스는 ArrayList
를 상속받아서 구현하고 있다.
Container
클래스는 put
과 extract
를 상위 클래스인 ArrayList
의 add
와 remove
를 이용하여 구현하고 있다.
올바른 사용법은 위 그림에 나타나 있는데, IDE는 상속받은 상위 클래스의 메소드도 제안으로 보여주기 때문에 원치 않는 동작을 개발자가 오용하여 사용하게 될 수 있다.
이것은 잘못 사용한 개발자의 문제일까?
Nope. 오용할 가능성이 높은 클래스를 만든 사람의 문제
public class FlowController {
private Encryptor encryptor = new Encryptor(); // 필드로 객체를 생성하여 조립
public void process() {
//...
byte[] encrytepdData = encryptor.encrypt(data);
//...
}
}
Storage 클래스를 상속하지 않고, 필드로 객체를 사용.
public class Container {
private int maxSize;
private int currentSize;
private List<Luggage> luggages = new ArrayList<>(); // 필드로 사용
public Container(int maxSize){
this.maxSize = maxSize;
}
public void put(Luggate lug) throws NotEnoughSpaceException {
if(!canContain(lug)) throw new NotEnoughSpaceException();
luggages.add(lug);
currentSize += lug.size();
}
public void extract(Luggage lug){
luggages.remove(lug);
this.currentSize -= lug.size();
}
public boolean canContain(Luggage lug){
return maxSize >= currentSize + lug.size();
}
}
위와 같이 ArrayList
를 상속받지 않고, 필드를 이용해 구현하면 오용의 가능성이 사라지게 된다.