2010-09-06 1 views
0

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

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(); 
    } 
} 

ответ

1

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

Мое предложение, чтобы все конкретные классы (например, Asub) переопределить метод клонирования и использовать copy constructor идиомы, чтобы создать точный клон себя ....

например

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 Сделать TopMostCloneable

+0

К сожалению, если 'ASub' также подклассифицирован, подкласс' 'clone()' не может вызывать 'super.clone()', поскольку он возвращает 'ASub' вместо 'ASubSub'. Таким образом, это работает только в том случае, если вы полностью контролируете всю иерархию классов навсегда (и тщательно документировали неконформистскую реализацию «клонирования» для своих преемников). –

+0

@ Péter Török, я полностью согласен с вами. –

+0

спасибо за ваш ответ – Joset

3

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

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

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

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

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

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

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

+1

Да и 'maybe' не потому, что' Cloneable' просто интерфейс маркера. –

+0

@ The Elite Gentleman, к сожалению, «Cloneable» - это не только интерфейс маркера. См. Мое обновление. –

+0

@ Péter Török, поэтому в итоге Asub глубоко клонирован, всем полям, включая те из абстрактных классов, была дана новая ссылка и копия? – Joset

0

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

+0

Извините, удалил другой someMethod, это должно быть только в TopMost – Joset