🙌 상속이란,
상속(Inheritance)란 하위 클래스가 상위클래스의 특성을 재정의한 것을 말한다. 부모 클래스의 메서드를 오버라이딩하여 자식에 맞추어 재사용하는 등, 상당이 많이 쓰이면서도 활용성이 높다.
상속의 단점
구현 상속(인터페이스 상속이 아닌)은 코드 재사용이 가능한 강력한 수단이면서도, 잘못 사용하면 객체의 유연성 / 캡슐화의 위반/ 다중 상속 불가 등의 결과를 초래한다.
상속의 오류 가능성이 있는 사례
/* * HashSet 의 요소를 몇번 삽입했는지 갯수를 출력하기 위해만든 클래스 * */ public class CustomHashSet<E> extends HashSet { private int addCount = 0; public CustomHashSet(){} public CustomHashSet(int initCap, float loadFactor){ super(initCap,loadFactor); } @Override public boolean add(Object o) { addCount++; return super.add(o); } @Override public boolean addAll(Collection c) { addCount+=c.size(); return super.addAll(c); } public int getAddCount() { return addCount; } } public class Main { public static void main(String[] args) { CustomHashSet<String> customHashSet = new CustomHashSet<>(); List<String> test = Arrays.asList("아","이","스"); customHashSet.addAll(test); System.out.println(customHashSet.getAddCount()); } }
--> 제대로 된 결과라면 ['아','이','스']로 3이 나와야 하지만 6이 나온다. 이유는 HashSet의 부모클래스를 살펴보면 된다.
public boolean addAll(Collection<? extends E> c) { boolean modified = false; for (E e : c) if (add(e)) modified = true; return modified; }
부모클래스에서 addAll메소드는 Collection의 객체 수만큼 add메소드를 수행한다. 우리가 커스텀한 클래스에서도 add메소드를 오버라이딩했으므로 총 6번의 add가 수행되면서 addCount의 값이 6으로 나온다.
상속의 단점인 기존의 클래스를 확장하는 것이 아니라, 새로운 클래스를 만들고 private필드로 기존 클래스의 인스턴스를 참조한 방식(Forwarding(전달))이다. 그래서 클래스의 구성요소로 쓰인다는 의미에서 Composition이라고 한다.
새로운 클래스는 기존의 클래스의 구현방식을 벗어나고, 기존 클래스는 새로운 메소드가 추가되더라도 전혀 영향을 받지 않는다.
has
또는 is part of
되는 경우, 컴포지션을 사용한다.public class CompositionExample{
public static void main(String.. houseComposition){
new House(new Bedroom(), new LivingRoom());
// The house is composed with a Bedrood and a LivingRoom
}
static class House{
Bedroom bedroom;
LivingRoom livingRoom;
House(Bedroom bedroom, LivingRoom livingRoom) {
this.bedroom = bedroom;
this.livingroom = livingroom;
}
static class Bedroom{}
static class LivingRoom{}
}
}
import java.util.HashSet;
public class CharacterBadExampleInheritance extends HashSet<Object> {
public static void main(String... badExampleOfInheritance) {
BadExampleInheritance badExampleInheritance = new BadExampleInheritance();
badExampleInheritance.add("Homer");
badExampleInheritance.forEach(System.out::println);
}
위의 예제는 매우 부적합한 상속의 예시이다.
컴포지션으로 바꿔보면
import java.util.HashSet;
import java.util.Set;
public class CharacterCompositionExample{
static Set<String> set = new HashSet<>();
public static void main(String.. goodExmapleOfComposition){
set.add('Homer');
set.forEach(System.out::println);
}
}
*참고 : https://github.com/gyoogle/tech-interview-for-developer/blob/master/Language/%5BJava%5D%20%EC%BB%B4%ED%8F%AC%EC%A7%80%EC%85%98(Composition).md , https://dev-cool.tistory.com/22, https://velog.io/@vino661/%EC%83%81%EC%86%8D%EA%B3%BC-%EC%BB%B4%ED%8F%AC%EC%A7%80%EC%85%98%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C