Клонирование объектов в Java [3 вопроса] - PullRequest
0 голосов
/ 06 сентября 2010

будет ли вызван метод клонирования Asub при этом?Или Асуб глубоко клонирован правильно?Если нет, то есть ли способ получить глубокий клон Асуб с помощью этого метода?

abstract class Top extends TopMost {
    protected Object clone() {
        Object obj = super.clone();
        // deep copy and try catch
    }


}

abstract class A extends Top { 
    protected Object clone() {
        Object obj = super.clone();
       // deep copy and try catch
    } 


}

class Asub extends A {
    protected Object clone() {
        Object obj = super.clone();
        // deep copy and try catch
    }

    public void doSomethingNew() {
    }
}

abstract class TopMost {
    public void someMethod() {
        Top a = (Top) super.clone();
        // more code here
    }
}

public class Main {
    public static void main(String... args) {
        Asub class1 = new Asub();
        class1.someMethod();
    }
}

Ответы [ 3 ]

3 голосов
/ 06 сентября 2010

Прежде всего, обратите внимание, что интерфейс clone () не работает , поэтому его не следует использовать в новом коде. Лучше реализовать конструктор (ы) копирования вместо .

Однако, если вам действительно нужно сделать это, правильный способ для TopMost - реализовать Cloneable. Зачем? Говорит Эффективное Java, 2-е издание, пункт 11:

Так что же делает Cloneable, учитывая, что он не содержит методов? Это определяет поведение защищенной Object реализации *1017*: если класс реализует Cloneable, метод клонирования Object возвращает полевую копию объекта; в противном случае он выбрасывает CloneNotSupportedException. Это очень нетипичное использование интерфейсов, а не один для эмуляции. Обычно реализация интерфейса говорит что-то о том, что класс может сделать для своих клиентов. В случае Cloneable, он изменяет поведение защищенного метода в суперклассе.

Более того, Asub.clone должно быть объявлено public, а не protected - иначе вы не сможете вызвать его из внешнего мира. Кроме того, если вы используете Java5 или выше, это законно и желательно, чтобы Asub.clone возвращал Asub, а не Object (и аналогично для его суперклассов).

Вы не показываете членов в классах - реализации clone в различных классах могут сильно отличаться в зависимости от типов членов в этом классе. А именно, если в классе есть непостоянные члены, вам необходимо тщательно их глубоко скопировать, в противном случае вы получите отдельные объекты, разделяющие их внутреннее состояние.

Однако, если у ваших классов есть только примитивные или неизменные поля, клонирование работает, как и ожидалось, хотя в ваших абстрактных классах есть много ненужных clone методов, каждый из которых просто вызывает super.clone() - вы можете быть лучше только с Asub.clone().

В качестве примечания: если Top a = (Top) super.clone() не является опечаткой, вы вводите зависимость от базового класса в производный класс, что не очень хорошая идея.

1 голос
/ 06 сентября 2010

Разрешение для всех abstract подклассов, реализующих super.clone(), по существу ничего не делает (поскольку все ваши абстрактные классы в вашем примере ничего не делают) и просто вызывает (в конце) Object.clone() метод.

Я предлагаю разрешить всем конкретным классам (например, ASub) переопределять метод клона и использовать конструктор копирования , чтобы создать точный клон самого себя ...

например.

public abstract class TopMost {

    public TopMost(TopMost rhs) {

    }

}

public abstract class Top extends TopMost {

    public Top(Top rhs) {
        super(rhs);

        //whatever you need from rhs that only is visible from top
    }
}

public abstract class A extends Top { 

    public A (A rhs) {
        super(rhs);

        //TODO: do rhs copy
    }
}

public class ASub extends A {

    public ASub(ASub rhs) {
        super(rhs);

        //TODO: copy other stuff here....
    }

    public Object clone() {
        return new ASub(this);
    }
}

PS Марка TopMost Клонирование

0 голосов
/ 06 сентября 2010

Вызов super.clone() отключает виртуальный механизм, поэтому он вызывает только Object.clone()

...