Existem alternativas para implementar Clone em Java?

votos
6

No meu projeto Java, eu tenho um vetor de vários tipos de Traders. Estes diferentes tipos de comerciantes são subclasses da classe Trader. Agora, eu tenho um método que leva um comerciante como um argumento e armazena 50 ou mais vezes no vector. Estou tendo problemas porque armazenar o mesmo objeto 50 vezes é apenas armazenar 50 referências de um mesmo objeto. Eu preciso armazenar 50 cópias do objeto. Eu pesquisei sobre a implementação de Clone , mas eu não quero que os programadores definem um tipo de Trader ter que se preocupar em fazer sua classe cloneable. Além disso, como apontado por esta página , implementando clone cria todos os tipos de problemas. Eu não acho que um construtor de cópia quer trabalhar, porque se eu definido um na classe Trader, não saberia o tipo de comerciante que estava copiando e apenas fazer um Trader genérico. O que eu posso fazer?

Edit: Eu não estou realmente querendo fazer cópias exatas de um certo objeto. O que eu estou realmente tentando fazer é adicionar um certo número de comerciantes ao vetor. O problema é que o usuário precisa especificar um argumento que tipo de Trader ele quer adicionar. Aqui está um exemplo do que estou tentando fazer: (embora a minha sintaxe é completamente imaginário)

public void addTraders(*traderType*)
{
    tradervect.add(new *traderType*())
}

Como posso conseguir algo parecido com isso em Java?

Publicado 27/04/2009 em 00:03
fonte usuário
Em outras línguas...                            


5 respostas

votos
0

Uma opção: Se você pode fazer os objetos serializado, você pode serializar seguida, desserializar-lo para fazer uma cópia, similar ao que acontece quando se passa um objeto sobre RMI.

método de cópia rápida:

public MyObject copy() {
    ObjectOutputStream oos = null;
    ObjectInputStream ois = null;
    try {
        ByteArrayOutputStream bos =  new ByteArrayOutputStream();
        oos = new ObjectOutputStream(bos);
        oos.writeObject(this);
        oos.flush();
        ByteArrayInputStream bin =
            new ByteArrayInputStream(bos.toByteArray());
        ois = new ObjectInputStream(bin);
        return (MyObject)ois.readObject();
    } catch(Exception e) {
        return null;
    } finally {
        try {
            oos.close();
            ois.close();
        } catch (Exception e) {
            return null;
        }
    }
}
Respondeu 27/04/2009 em 00:13
fonte usuário

votos
2

Basta adicionar um método de cópia abstrato. Você pode usar tipos de retorno covariantes de modo que o tipo derivado é especificado para retornar uma instância derivada, que pode ou não ser importante.

public interface Trader {
    Trader copyTrader();
    ...
}


public final class MyTrader implements Trader {
    MyTrader copyTrader() {
        return new MyTrader(this);
    }
    ...
}

Às vezes você pode querer genericamente lidar com uma coleção de tipo derivado de Traderque precisa para clonar e, em seguida, retornar a uma coleção corretamente digitado. Para isso você pode usar os genéricos de forma idiomática:

public interface Trader<THIS extends Trader> {
    THIS copyTrader();
    ...
}


public final class MyTrader implements Trader<MyTrader> {
    public MyTrader copyTrader() {
        return new MyTrader(this);
    }
    ...
}
Respondeu 27/04/2009 em 00:27
fonte usuário

votos
-2

É uma maneira de torná-lo uma classe final como própria Cadeia de Java, que vai fazer qualquer alteração em um objeto de Trader classe para criar uma nova cópia na memória, mas ele vai fazer com que seja impossível para subclasse-lo.

Outro (melhor) maneira é usar um método de fábrica para criar e copiar objexts do comerciante, o que implica que você não deve permitir o construtor padrão para ser usado ou seja, torná-lo um privado. Desta forma, você pode controlar o número de instâncias da classe tem. veja http://en.wikipedia.org/wiki/Factory_method

public class Trader {

    /* prevent constructor so new cant be used outside the factory method */
    private Trader() {
    }

    /* the factory method */
    public static Trader createTrader(int whatKindOfTrader) {

        switch (whatKindOfTrader) {
        case 0:
            return new Trader1(); // extends Trader
        case 1:
        default:
            return new Trader2(); // extends Trader
        }
        return new Trader3(); // or throw exception
    }
}

Você pode até especificar outro método sobrecarregado, ou um segundo argumento que leva um Trader e copia-o para um novo, substituindo assim clone. Btw, você pode querer substituir o método clone () e jogar CloneNotSupportedException, para evitar a clonagem de objeto padrão.

Respondeu 27/04/2009 em 00:29
fonte usuário

votos
2

Estou um pouco claro por que motivo você gostaria de armazenar 50 ou mais clones de um mesmo objeto, a menos que o comerciante originais serve como um protótipo (ver padrão) para os comerciantes posteriores.

Se você quiser fazer uma cópia exata de um objeto, você tem que levar em conta a questão de polimorfismo. Se as pessoas Subclassing sua classe dada tem permissão para adicionar membros de estado, então você já tem o suficiente de uma dor de cabeça com funções como iguais e compareTo, que clone é jut mais um caso onde você precisa requerem um tratamento especial.

Eu discordo que clone é sempre o mal, às vezes é necessário. No entanto, em situações de subclassificação, um monte de coisas tornam-se complicado.

Eu recomendo que você leia (quando você tem a chance) "Effective Java" de Bloch, que abrange uma série de seus temas. A visão de Bracha é que ele não é uma boa idéia para deixar os outros estender suas classes, e que se você fizer isso, você precisa documentar muito bem o que teria que fazer e espero que eles sigam suas instruções. Não há realmente uma maneira de contornar isso. Você também pode querer fazer seus comerciantes imutável.

Vá em frente um implemento Clone normalmente, e indicam muito claramente no cabeçalho classe que ninguém herdar de seu Trader e adicionando membros de estado deve implementar métodos X (especificar quais).

Encontrar truques para contornar uma Cloneable real e ainda Clone não vai superar o problema da herança. Não há nenhuma bala de prata aqui.

Respondeu 27/04/2009 em 00:31
fonte usuário

votos
0

direito de Uri, polimorfismo com o estado abre uma grande lata de vermes.

Eu acho que subclassificação Cloneable e overrideing clone () é provavelmente a maneira mais simples para ir. Você pode, creio eu, fazer o tipo de retorno covariant.

Respondeu 27/04/2009 em 03:49
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more