2010-10-27 13 views
19

Estoy tratando de entender el polimorfismo de Java, y tengo una pregunta acerca de la idea de descifrar un objeto. Digamos que para este ejemplo tengo dos subclases de Perros y Gatos que heredan de un animal superclaseCómo abatir un objeto Java?

Por lo que entendí, la única manera de abatido un objeto es si este objeto ya de la buena tipo es, de esta manera:

Animal a = new Dog(); 
Dog d = (Dog) a; 

Esto funciona ¿verdad?

Pero, ¿y si quiero crear un animal común sin saber qué sería, y luego lanzarlo cuando lo sepa, cómo puedo hacerlo?

Animal a = new Animal(); 
Dog d = (Dog) a; 

Esto lanzará una ClassCastException en tiempo de ejecución ¿verdad?

La única manera que encontré para hacer esto es crear un nuevo constructor de perro que crea un perro de un animal normal:

Animal a = new Animal(); 
Dog d = new Dog(a); 

con

public Class Dog extends Animal{ 
    public Dog(Animal a){ 
     super(a); 
    } 
} 

Así que mi pregunta es, ¿soy ¿Debo hacer esto?

  • ¿Lo estoy haciendo de la mejor manera?
  • ¿Se supone que no debo hacer esto en absoluto, si tengo que hacerlo significa que mi programa no está bien concebido?
  • ¿Hay alguna manera mejor que me haya perdido?

¡Muchas gracias! nbarraille

Respuesta

8

Si desea crear una instancia de un tipo que puede variar según las condiciones no locales, utilice un Abstract Factory (como se describe en el libro Patrones de diseño).

En su forma más simple:

interface AnimalFactory { 
    Animal createAnimal(); 
} 

class DogFactory implements AnimalFactory { 
    public Dog createAnimal() { 
     return new Dog(); 
    } 
} 

Tenga en cuenta también que hay una diferencia entre el tipo estático de referencia y el tipo dinámico del objeto. Aunque tiene una referencia Animal, si el objeto original es Dog, todavía se comporta como Dog.

1

Java es un lenguaje fuertemente tipado, y eso significa que solo puede convertir un objeto a un tipo desde el que se extiende (ya sea una superclase o una interfaz).

Incluso si lo "falsifica", p. copie todos los métodos y campos de una clase, simplemente no puede convertir un objeto a un tipo que no se extienda.

public class Foo{ 

    public String phleem; 

    public void bar(){ 

    } 

} 

public class Bar{ 

    public String phleem; 

} 

public interface Baz{ 

    public void bar(); 

} 

Teniendo en cuenta el código anterior, no se puede convertir un objeto Foo ya sea a un Bar o una Baz, aunque la estructura de clases parece dar a entender que podía. No hay herencia involucrada, por lo que se arroja un ClassCastException.

3

Sólo debe convertirse a una clase que el objeto es en realidad, así que si usted tiene un Dog que se extiende Animal puede convertir a un Animal (ya que es uno), pero no se debe emitir un Animal a un Dog porque no todos Animal s son Dog s. La clase Dog puede tener campos adicionales que no están implementados por la clase Animal, por lo que el molde no tiene sentido (¿a qué inicializa esos valores?).

0

Aquí está hablando de downcasting, por lo que en este escenario siempre debe usarse superclase como referencia y el objeto secundario debe apuntar a eso. Esto usd básicamente en el patrón de fábrica.

Cuestiones relacionadas