superclase sirve simple resueltos que polimorfismo para metodo llamar herencia ejercicios como comando clase java inheritance constructor

sirve - Java: creación de un objeto de subclase a partir de un objeto primario



super en java (10)

¿Tendría que escribir mi propio constructor de copia? Esto debería actualizarse cada vez que Car obtiene un nuevo campo ...

¡De ningún modo!

Pruebe de esta manera:

public class Car{ ... } public class Truck extends Car{ ... public Truck(Car car){ copyFields(car, this); } } public static void copyFields(Object source, Object target) { Field[] fieldsSource = source.getClass().getFields(); Field[] fieldsTarget = target.getClass().getFields(); for (Field fieldTarget : fieldsTarget) { for (Field fieldSource : fieldsSource) { if (fieldTarget.getName().equals(fieldSource.getName())) { try { fieldTarget.set(target, fieldSource.get(source)); } catch (SecurityException e) { } catch (IllegalArgumentException e) { } catch (IllegalAccessException e) { } break; } } } }

Newbie pregunta de Java. Digamos que tengo:

public class Car{ ... } public class Truck extends Car{ ... }

Supongamos que ya tengo un objeto Car, ¿cómo creo un objeto Truck nuevo a partir de este objeto Car para que todos los valores del objeto Car se copien en mi nuevo objeto Truck? Idealmente podría hacer algo como esto:

Car c = new Car(); /* ... c gets populated */ Truck t = new Truck(c); /* would like t to have all of c''s values */

¿Tendría que escribir mi propio constructor de copia? Esto debería actualizarse cada vez que Car obtiene un nuevo campo ...


¿Tendría que escribir mi propio constructor de copia? Esto debería actualizarse cada vez que Car obtiene un nuevo campo ...

Esencialmente, sí, no se puede simplemente convertir un objeto en Java.

Afortunadamente, no tiene que escribir todo el código usted mismo: consulte commons-beanutils , específicamente métodos como cloneBean . ¡Esto tiene la ventaja adicional de que no tiene que actualizarlo cada vez que obtiene un nuevo campo!


Las soluciones presentadas anteriormente tienen limitaciones que debe tener en cuenta. Aquí hay un breve resumen de algoritmos para copiar campos de una clase a otra.

  • Tom Hawtin : Usa esto si tu superclase tiene un constructor de copia. Si no lo hace, necesitará una solución diferente.
  • Christian : usa esto si la superclase no extiende ninguna otra clase. Este método no copia los campos recursivamente hacia arriba.
  • Sean Patrick Floyd : Esta es una solución genérica para copiar todos los campos recursivamente hacia arriba. Asegúrese de leer el comentario de @ jett de que se debe agregar una sola línea para evitar un bucle infinito.

Reproduzco la función de analyze Sean Patrick Floyd con la declaración faltante:

private static Map<String, Field> analyze(Object object) { if (object == null) throw new NullPointerException(); Map<String, Field> map = new TreeMap<String, Field>(); Class<?> current = object.getClass(); while (current != Object.class) { Field[] declaredFields = current.getDeclaredFields(); for (Field field : declaredFields) { if (!Modifier.isStatic(field.getModifiers())) { if (!map.containsKey(field.getName())) { map.put(field.getName(), field); } } } current = current.getSuperclass(); /* The missing statement */ } return map; }


Necesitarás un constructor de copia, pero tu constructor de copia puede usar la reflexión para encontrar los campos comunes entre los dos objetos, obtener sus valores del objeto "prototipo" y establecerlos en el objeto hijo.


Puede utilizar la API de reflexión para recorrer cada uno de los campos de Carro y asignar el valor a los campos de Camión equivalentes. Esto se puede hacer dentro del camión. Además, es la única forma de acceder a los campos privados de Automóvil, al menos en un sentido automático, siempre que no haya un administrador de seguridad y restrinja el acceso al campo privado.


Sí, solo agrega un constructor a Truck. Probablemente también quiera agregar un constructor a Car, aunque no necesariamente público:

public class Car { protected Car(Car orig) { ... } public class Truck extends Car { public Truck(Car orig) { super(orig); } ... }

Como regla, generalmente es mejor hacer que las clases sean hojas (y es posible que desee marcar las finales) o abstractas.

Parece que quiere un objeto de Car y luego la misma instancia se convierte en Truck . Una mejor forma de hacerlo es delegar el comportamiento a otro objeto dentro de Car ( Vehicle ). Asi que:

public final class Vehicle { private VehicleBehaviour behaviour = VehicleBehaviour.CAR; public void becomeTruck() { this.behaviour = VehicleBehaviour.TRUCK; } ... }

Si implementa Cloneable , puede copiar "automáticamente" un objeto a una instancia de la misma clase. Sin embargo, hay una serie de problemas con eso, como tener que copiar cada campo de objetos mutables que es propenso a errores y prohíbe el uso de final.


Sí, tienes que hacer esto manualmente. También deberá decidir cómo copiar las cosas "profundamente". Por ejemplo, supongamos que el automóvil tiene una colección de llantas; podría hacer una copia superficial de la colección (de modo que si el objeto original cambia el contenido de su colección, el nuevo objeto también vería el cambio) o podría hacer una profunda copia que creó una nueva colección.

(Aquí es donde los tipos inmutables como String suelen ser útiles, no es necesario clonarlos, solo puede copiar la referencia y saber que el contenido del objeto no cambiará).


Si está utilizando Spring en su proyecto, puede usar ReflectionUtils.


Siempre puede usar un Marco de mapeo como Dozer . De forma predeterminada (sin configuración adicional ), asigna todos los campos del mismo nombre de un objeto a otro utilizando los métodos getter y setter.

Dependencia:

<dependency> <groupId>net.sf.dozer</groupId> <artifactId>dozer</artifactId> <version>5.5.1</version> </dependency>

Código:

import org.dozer.DozerBeanMapper; import org.dozer.Mapper; // ... Car c = new Car(); /* ... c gets populated */ Truck t = new Truck(); Mapper mapper = new DozerBeanMapper(); mapper.map(c, t); /* would like t to have all of c''s values */


puedes usar el reflejo lo hago y funciona bien para mí:

public Child(Parent parent){ for (Method getMethod : parent.getClass().getMethods()) { if (getMethod.getName().startsWith("get")) { try { Method setMethod = this.getClass().getMethod(getMethod.getName().replace("get", "set"), getMethod.getReturnType()); setMethod.invoke(this, getMethod.invoke(parent, (Object[]) null)); } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { //not found set } } } }