2015-05-06 4 views
3

Я прочитал Effective Java по J.Bloch и здесь было написано:Java клон() метод

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

У меня есть класс A:

public class A{} 

и класс B, который расширяет класс А:

public class B extends A implements Cloneable { 

} 

Так что в этом случае я не могу, чтобы переопределить clone() метод? Если да, чем объясните, почему.

+0

Используйте конструктор копирования. – Everv0id

+0

Да, я понимаю, что конструктор копирования - лучший способ скопировать объект ..thanks :) –

+0

Для других: альтернативой конструктору копирования является [static newInstance()] (http://www.javapractices.com/topic /TopicAction.do?Id=12) идиома. Но я нахожу это любопытным. Почему бы просто не сделать свой класс собственной фабрикой и использовать нестатический метод 'newInstance()? Кажется более чистым, чем передача существующего объекта в качестве параметра; как объект для копии самого себя (без использования сломанного 'clone()'). –

ответ

2

В вашем случае да, вы можете переопределить clone():

public class A { 
} 

public class B extends A implements Cloneable { 

    @Override 
    public B clone() throws CloneNotSupportedException { 
     return (B) super.clone(); 
    } 
} 

и до сих пор эффективный механизм клонирования - вы поэтому говорить правду, когда вы заявляете implements Cloneable.

Однако все, что необходимо для разрыва этого обещания, должно дать A переменную private.

public class A { 
    private int a; 
} 

и теперь ваше обещание нарушается - если А не реализует clone, в этом случае вы можете использовать super.clone():

public class A { 

    private int a; 

    @Override 
    public A clone() throws CloneNotSupportedException { 
     A newA = (A) super.clone(); 
     newA.a = a; 
     return newA; 
    } 
} 

public class B extends A implements Cloneable { 

    private int b; 

    @Override 
    public B clone() throws CloneNotSupportedException { 
     B newB = (B) super.clone(); 
     newB.b = b; 
     return newB; 
    } 
} 

По сути - Джошуа Блох утверждает, - если вы не реализуете clone ваш суб -классы также не могут (вообще).

+1

Это просто неверно. Частное поле в A будет клонировано 'Object.clone()'. – EJP

1

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

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

+1

Откуда ваше первое утверждение ('Cloneable' устарело)? –

+1

Много дискуссий об этом, [здесь] (http://stackoverflow.com/questions/709380/java-rationale-of-the-cloneable-interface) одно место. На самом деле «Cloneable» не ** устарел **, он ** сломан **. – Kayaman

+1

Ну, я полностью согласен с «сломанной» частью. Я просто подумал, что я пропустил часть устаревания. –

0

Конечно, вы можете реализовать B.clone().

Проблема, с которой Дж Блох относится к является (IIRC), что без хорошего A.clone() метода, частные поля в пределах не может быть правильно клонированы в B. Простой пример:

public class A { 
    private String myText; 
    public A (String myText) { 
    this.myText = myText; 
    } 
    public String getExtendedText() { 
    return "Hello something " + myText; 
    } 
} 

public class B extends A implements Cloneable { 
    private int someValue; 
    // getter/setter 

    public clone() { 
     // how can you now provide a good clone with A.myText being cloned? 
    }  
} 
+0

'A.myText' и' B.someValue' будут клонированы автоматически с помощью 'Object.clone()'. 'B.clone()' не нужно ничего делать, кроме вызова 'super.clone()' в этом случае. – EJP

Смежные вопросы