Pergunta

Hullo All,

Quer saber se há algum hackers Java que possa me indicar por que o seguinte não funciona:

public class Parent {
    public Parent copy() {
       Parent aCopy = new Parent();
       ...
       return aCopy;
    }
}

public class ChildN extends Parent {
    ...
}

public class Driver {
     public static void main(String[] args) {
         ChildN orig = new ChildN();
         ...
         ChildN copy = orig.getClass().cast(orig.copy());
     }
}

O código está muito feliz em compilar, mas decide lançar uma classe ClassCexception no tempo de execução d =

Editar: Whoah, respostas muito rápidas. Obrigado rapazes! Então, parece que não posso abaixar o uso desse método ... Existe outra maneira de fazer abatida no Java? Eu pensei em ter cada um ChildN Substituição de classe copy(), mas não estava entusiasmado em adicionar o código de caldeira extra.

Foi útil?

Solução

(Não é possível adicionar código em um comentário, então adicionarei aqui)

Em relação ao clonável: se você estiver implementando clonável, implemente -o da seguinte forma; Muito mais limpo para ligar ...

public class Foo implements Cloneable {
    public Foo clone() {
        try {
            return (Foo) super.clone();
        } catch (CloneNotSupportedException e) {
            return null; // can never happen!
    }
}

Editar: eu também vi outras pessoas usarem

throw new AssertionError("This should never happen! I'm Cloneable!");

no bloco de captura.

Outras dicas

É como tentar fazer isso:

  public Object copy(){
       return new Object();
  }

E então tente::

  String s = ( String ) copy();

Sua Pai classe e Childn classe tem o mesmo relacionamento que Objeto e Corda

Para fazer funcionar, você precisaria fazer o seguinte:

public class ChildN extends Parent {
    public Parent copy() {
        return new ChildN();
    }
}

Isto é, substitua o método "cópia" e retorne a instância correta.


EDITAR

De acordo com sua edição. Isso é realmente possível. Esta pode ser uma maneira possível:

public class Parent {
    public Parent copy() {
        Parent copy = this.getClass().newInstance();
        //...
        return copy;
    }
}

Dessa forma, você não precisa substituir o método "cópia" em cada subclasse. Este é o padrão de design do protótipo.

No entanto, usando esta implementação, você deve estar ciente de duas exceções verificadas. Aqui está o programa completo que compila e funciona sem problemas.

public class Parent {
    public Parent copy()  throws InstantiationException, IllegalAccessException  {
       Parent copy = this.getClass().newInstance();
       //...
       return copy;
    }
}
class ChildN  extends Parent {}

class Driver {
     public static void main(String[] args) throws  InstantiationException ,  IllegalAccessException  {
         ChildN orig = new ChildN();
         ChildN copy = orig.getClass().cast(orig.copy());
         System.out.println( "Greetings from : " + copy );
    }
}

O elenco está tentando efetivamente fazer isso:

ChildN copy = (ChildN) orig.copy();

(Está resolvendo o elenco para se apresentar no momento da execução, mas é isso que será porque orig.getClass() vai ser ChildN.class) No entanto, orig.copy() não retorna uma instância do Childn, ele retorna uma instância de apenas Parent, então não pode ser lançado para ChildN.

Se Childn não substituir a copy () para retornar uma instância do Childn, você está tentando abaixar um objeto do tipo pai para digitar Childn

java.lang.class#elenco (objeto) lança uma classe de classe se a classe#isinstance () retornar falsa. Do javadoc para esse método:

Determina se o objeto especificado é compatível com a atribuição com o objeto representado por esta classe. Este método é o equivalente dinâmico da instância da linguagem java do operador ... especificamente, se isso Class Objeto representa uma classe declarada, esse método retorna true se o especificado Object O argumento é uma instância da classe representada (ou de qualquer uma de suas subclasses); ele retorna false por outro lado.

Como o pai não é uma subclasse do filho, o isinstance () retorna false, então o elenco () lança a exceção. Isso pode violar o princípio de menos espanto, mas está funcionando da maneira que está documentada - o elenco () só pode ser aprimorado, não abatido.

Pode ser que você simplesmente quer uma cópia/clone de seu objeto.

Nesse caso, implementar a interface Cloneable e substituir o clone (), se necessário.

public class Parent implement Cloneable {
   public Object clone() throws CloneNotSupportedException {
     Parent aCopy = (Parent) super.clone();
   ...
   return aCopy;
   }
}

public class ChildN extends Parent {
    ...
}

public class Driver {
     public static void main(String[] args) {
         ChildN orig = new ChildN();
         ...
         ChildN copy = orig.getClass().cast(orig.clone());
     }
}

Isso faz exatamente o que o seu "(cópia)" método tentei fazer em Java.

(Sim, você poderia fazer a fantasia de introspecção jogos também, mas esses métodos falham ou tornar-se feio assim que você não tem um público padrão-construtor.Clone funciona em qualquer caso, não importa o que os construtores que você tem.)

A razão downcasting não funciona é porque, ao lançar um objeto pai para uma criança escreva, não há nenhuma maneira que você pode chamar de criança tipo de métodos no objeto pai.Mas ele funciona de outra maneira...

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top