javacloneableeffective-java

Effective Java. Clonable interface


I read Effective Java book and don't understand one paragraph where explained Clonable interface. Can someone explain me this paragraph:

...programmers assume that if they extend a class and invoke super.clone from the subclass, the returned object will be an instance of the subclass. The only way a superclass can provide this functionality is to return an object obtained by calling super.clone. If a clone method returns an object created by a constructor, it will have the wrong class.

Thanks.


Solution

  • I should note to begin with that clone in and of itself is broken, and that a copy constructor, like Sheep(Sheep cloneMe) is a far more elegant idiom than clone, considering the Cloneable contract is very weak. You probably already know this, since you're reading the book, but it's worth putting in here.

    Anyway, to answer the question:

    Object.clone() will create an object of the same type as the object it was called on. For this reason, it is strongly encouraged to "cascade" up to Object for getting the result you plan to return. If someone decides to not follow this convention, you will end up with an object of the type of the class that broke the convention, which will cause a multitude of problems.

    To illustrate I have a class like so

    class Sheep implements Cloneable {
    
        Sheep(String name)...
    
        public Object clone() {
            return new Sheep(this.name); // bad, doesn't cascade up to Object
        }
    }
    
    class WoolySheep extends Sheep {
    
        public Object clone() {
            return super.clone();
        }
    }
    

    Suddenly, if I do

    WoolySheep dolly = new WoolySheep("Dolly");
    WoolySheep clone = (WoolySheep)(dolly.clone()); // error
    

    I'll get an exception because what I get back from dolly.clone() is a Sheep, not a WoolySheep.