내용이 어렵다..나중에 다시 정리하도록 하자..


cloneable은 어떤 객체가 복제를 허용한다는 사실을 알리는데 쓰려고 고안된 인터페이스다. cloneable 인터페이스에는 어떠한 메소드도 없는데 그렇다면 대체 Cloneable이 하는 일은 무엇일까? protected로 선언 된 Object의 clone메서드가 어떻게 돚악할지 정하는 역할을 한다. Cloneable 인터페이스를 구현하면 해당 객체를 필드 단위로 복사한 객체를 반환한다. 구현하지 하지 않은 클래스라면 CloneNotSupportedException이 발생한다.

사실 인터페이스라는 것은 클라이언트에게 해당 클래스가 무슨 일을 할 수 있는지 알리는 것인데, Cloneable은 상위 클래스의 protected 메서드의 동작을 규정하는 역할을 하고 있으므로 좀 이상하다..

비 fianl 클래스에 clone을 재정의할 때는 반드시 super.clone을 호출해 얻은 객체를 반환해야 한다.
why? 만약 하위클래스에서 super.clone()을 호출하면 프로그래머는 하위 클래스 객체가 반환될 것이라고 생각할 수 있다. 하지만 이러한 기능을 제공하려면 상위 클래스에서도 다시 super.clone을 호출해 만든 객체를 적절히 변환해서 반환할 수 밖에 없다. 모든 상위클래스가 이런식으로 동작을 하게 된다면 결국 Object의 clone메서드를 호출하게 될 것이다.
>> 사실 why에 대한 답이 아닌 것같다...본인조차도 이해가 잘 안되는..추후에 다시 공부하였을 떄 정리할 수 있으면 하도록 해야지..

clone을 정의해야할 때 주의해야 할 점은 복재할 객체가 변경 가능 객체에 대한 참조필드를 가지고 있다면 일반적인 방법으로는 오동작하게 될 확률이 매우매우매우 높다. 

 위의 두 클래스가 있다고 했을 때, 단순히 super.clone을 해버리면 원본 객체와 복사 된 객체가 obj에 대한 같은 참조값을 가지게 되므로 문제가 생긴다. clone메소드 또 다른 형태의 생성자로 볼수 있다. 원래 객체를 손상시키는 일이 없도록 해야하고, 복사본의 불변식도 제대로 만족해야 한다. 

이러한 문제는 clone을 재귀적으로 호출하여 처리할 수 있다. 


정리

Cloneable을 구현하는 모든 클래스는 반환값 자료형이 자기 자신인 public clone 메서드를 재정의해야한다. 이 메서드는 처음에 super.clone을 호출해야 한다. 만일 클래스 내부 필드가 전부 기본형이거나 변경 불가능 객체에 대한 참조라면 필드를 수정할 필요는 없지만(일련 번호같은 필드는 제외) , 참조 필드에 대한 복사는 재귀호출을 이용하여 deepCopy를 하여야 한다. 
 또 다른 객체 복제를 지원하는 좋은 방법은, 복사 생성자나 복사 팩터리를 제공하는 것이다. 


+ Recent posts