Java: почему класс, предназначенный для наследования, должен содержать защищенный метод клонирования?

Я внимательно читаю "Эффективную Java" (Джошуа Блох) и нашел следующее предложение о клонировании:

Если вы разрабатываете класс для наследования, имейте в виду, что если вы решите не предоставлять хорошо защищенный метод клонирования, для подклассов будет невозможно реализовать Cloneable.

Я немного запутался, потому что в моем маленьком тесте:

public class Cloning {

    public static void main(String[] args) throws CloneNotSupportedException {

        Woman woman1 = new Woman("Marie Curie-Sklodowska", 33, "Physics");
        Woman woman2 = (Woman) woman1.clone();
    }

    static abstract class Person {
        protected String name;
        protected int age;

        Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    }

    static class Woman extends Person implements Cloneable {

        private String field;

        Woman(String name, int age, String field) {
            super(name, age);
            this.field = field;
        }

        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }
}

Я не получаю никакой ошибки. Я думаю, я не правильно понимаю предложение. Может кто-нибудь объяснить, что имел в виду автор?

1 ответ

Решение

Если вы разрабатываете класс для наследования, имейте в виду, что если вы решите не предоставлять хорошо защищенный clone() метод, для подклассов будет невозможно реализовать Cloneable,

Он не прав. Они могут. Рассматривать:

public class A
{
    private int fieldA;
}

public class B extends A implements Cloneable
{
    public B clone() throws CloneNotSupportedException
    {
        return (B)super.clone();
    }
}

B.clone() вернет идеальную копию экземпляра B он вызывается, в том числе A.fieldA, Опровергнуто контрпримером: QED

[Я знаю, что это clone() не должно быть объявлено, чтобы бросить CloneNotSupportedException но это упрощает демонстрацию.]

Это все очень любопытно, потому что пару предложений ранее он только что сказал:

некоторые программисты просто решили никогда не отменять clone() метод

а также

классы, предназначенные для наследования, не должны его реализовывать [Cloneable]

Что еще более любопытно, так это то, что первое предложение выше является последним предложением во всем разделе и полностью не поддерживается ни аргументом, ни примером, если только весь раздел не призван это доказать, а это не так. Весь раздел настолько запутан, что трудно точно определить, что именно заявлено. Клонирование не так сложно понять или реализовать, как он делает. И это не важно. Я не использовал его в серьезном коде за 20 лет Java или так называемых "конструкторов копирования".

Другие вопросы по тегам