- 믹스인(mixin) : 다른 클래스에서 사용할 목적으로 만들어진 클래스, 포함으로 설명되며 상속의 단점을 해결해준다.
- 클래스가 구현할 수 있는 타입, 믹스인을 구현한 클래스에 원래의 ‘주된 타입’ 외에도 특정 선택적 행위를 제공한다고 선언하는 효과를 준다.(ITEM20)
- 인터페이스를 이례적으롯 사용한 예, 따라 하지 말자.
x.clone() != x
: 참x.clone().getClass() == x.getClass()
: 참x.clone().equals(x)
: 참, 필수는 아님x.clone().getClass() == x.getClass()
: 관례상 super.clone을 호출해야하는데 그 관례를 따른다면 참
- 원본 필드와 똑같은 값을 가진다.
@Override public PhoneNumber clone(){
try{
return (PhoneNumber) super.clone();
}catch(CloneNotSupportedException e){
throw new AssertionError(); //PhoneNumber 클래스에 Cloneable만 구현되어 있으면 있어날 수 없는 일
}
}
- 공변 변환 타이핑(covariant return typing) : 부모 클래스의 메소드를 오버라이딩하는 경우, 부모 클래스의 반환 타입은 자식 클래스의 타입으로 변경 가능하다.
- T’가 T의 subType이면, C<T’>는 C
의 SubType이다.
public class Stack{
private Object[] elements;
private int size;
}
@Override public Stack clone() {
try {
Stack result = (Stack) super.clone();
result.elements = elements.clone();
return result;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
1 . 해시테이블의 clone 메소드는 적절한 크기의 새로운 버킷 배열을 할당한다. 2 . 다음 원래의 버킷 배열을 순회하며 비지 않은 버킷에 대해 깊은 복사(HashTable.Entry의 deep copy)를 수행
- 버킷이 길기 않다면 잘 작동한다. 하지만 그렇게 좋은 방식은 아님 > 재귀호출 때문에 스택 프레임을 소비하여 리스트가 길면 스택 오버플로를 일으킬 수 있다.
put(key, value)
- 간단한 코드를 얻을 수 있지만 저수준 API보다는 느리고 필드 단위 객체 복사를 우회하므로 전체 Cloneable과 어울리지 않는 방식이기도 하다.
@Override
protected final Object clone() throws CloneNotSupportedException{
throw new CloneNotSupportedException();
}
- clone이 하위 클래스에서 재정의한 메소드를 호출하면 하위 클래스는 복제 과정에서 자신의 상태를 교정할 기회를 잃는다. > 원본, 복제본 상태가 달라짐
public Yum(Yum yum){...};
public static Yum newInstance(Yum yum){...};
- 인터페이스 기반 복사 생성자 = 변환 생성자 (conversion constructor)
- 인터페이스 기반 복사 팩터리 = 변환 팩터리 (conversion factory)
Reference: