Así que soy bastante nuevo en la programación en el mundo real (fuera de los proyectos académicos) y he encontrado muchas publicaciones que dicen que usar instanceof
es algo malo para determinar qué clase es un objeto específico.
Mi situación es que tengo tres clases, una clase de producto base, una que se extiende fuera de eso y otra que se extiende fuera de eso. Todos estos se almacenan en la misma tabla en una base de datos y tengo un código que necesita usar los métodos en cada uno para extraer datos de ellos.
¿Cuál es la mejor práctica para evitar esta forma de hacerlo? He leído algunas cosas sobre el polimorfismo, pero no puedo encontrar ningún ejemplo que solucione el problema que tengo. Por lo general, todos anulan un método que para mí no funcionará, ya que necesito extraer diferentes cosas de los diferentes objetos.
¿Hay una mejor manera de hacer esto o estoy atascado con el uso instanceof
o algún tipo de reflexión para obtener los campos específicos de los objetos?
fuente
instanceof
esté mal; Tratar de encontrar la clase de un objeto suele ser el problema. No siempre está mal, pero probablemente lo sea en tu caso. Tal vez si nos dice lo que está tratando de lograr, podemos sugerirle una solución con polimorfismo.getSpecifics()
que se implementa de manera diferente en cada uno, y cada uno devuelve los datos específicos de la clase.Respuestas:
La razón que
instanceof
se desaconseja es que no es POO.No debería haber ninguna razón para que el llamante / usuario de un objeto sepa de qué clase concreta es una instancia más allá de qué tipo de variable se declara como variable.
Si necesita un comportamiento diferente en las subclases, agregue un método e impleméntelos de manera diferente.
fuente
getSpecifics()
(o algo similar) en cada clase que devolverá los detalles para cada clase. ¿Es este el mejor enfoque?List
. Lo paso a un objeto que tome cualquieraIterable
. Ahora ese segundo objeto lo pasa a un tercer objeto que toma unaList
optimización, o unaIterable
pero es mucho más lento. El segundo no debería saber que es una lista, pero al tercero le gustaría saberlo. ¿No debería comprobar el tercer objeto, por ejemplo, para ver si puede aplicar la optimización? Ver, por ejemplo, guayabaFluentIterable
que hace exactamente eso.instanceof
.instanceof
no es necesariamente algo malo, sin embargo, es algo que uno debe mirar.Un ejemplo de dónde funciona correctamente es en un lugar donde se obtiene una colección del tipo base y solo se desean los de un subtipo. Obtener las direcciones de red
NetworkInterface.getNetworkInterfaces()
devuelve los objetos NetworkInterface que tienen una colección de objetos InetAddress, algunos de los cuales son Inet4Address y otros son Inet6Address. Si se quiere filtrar la colección de objetos Inet4Address, es necesario usar instanceof.En la situación que se describe en la publicación original, hay una clase Base, algo que extiende esa clase base y algo que extiende la clase extendida. Si bien no es completamente informativo, parece tener las bases de un diseño menos que ideal.
Cuando devuelve una clase base, a menos que haya una buena razón para que se diseñe de esa manera (compatibilidad hacia atrás entre las especificaciones de una versión anterior), no debería intentar echar un vistazo a los tipos subyacentes. Si le devuelven un conjunto, sabe que está obteniendo un conjunto. Le permite al desarrollador cambiar más tarde de opinión para devolver un tipo más específico (SortedSet) o cambiar el tipo subyacente (HashSet a TreeSet) sin romper nada.
Reconsidere su diseño de cómo los objetos están estructurados y parentales para ver si uno puede hacer un mejor modelo de clase que no requiera una distinción de tipos.
fuente
isOfType(SomeEnum.IPv4)
método podría ser una mejor manera de filtrar esas cualidades que inspeccionar el tipo de concretoinstanceof
. ¿Qué sucede si desea dividir su clase de implementación de IPv4 más tarde? No es que esto siempre sea mejor, pero es una consideración.(o instanceof Serializable) || (o instanceof Externalizable)
. instanceof es mejor que la alternativaPuede usar el método getClass ().
¿Estás seguro de que necesitas tres clases diferentes? ¿Tal vez una clase con un interruptor adentro servirá mejor?
fuente
getClass
yinstanceof
compartir desventajas. El polimorfismo es mejor que ambos cuando encaja, y no veo que no se ajuste al caso de uso de OP.getClass
puedo todavía no compartir el mismo problema que el usoinstanceof
? Todavía tendré que averiguar cuál tengo y luego llamar a un conjunto de funciones. Idealmente, quiero un método que devuelva los datos específicos de esa clase sin necesidad de convertir a ese objeto.getClass
es una mejor manera de hacerlo, no tiene nada que ocupar la mayor parte de una respuesta ;-)Por lo general, cuando me encuentro con ganas de saber el tipo de algo, significa que implementé mal la estructura de mi objeto. La mayoría de estas veces se trata de violar el LSP .
Sin embargo, hay momentos en los que desearía tener una forma de hacer un despacho dinámico y ahorrar una tonelada de código de placa de caldera y proteger mi estructura de objetos en el futuro. C # proporciona la palabra clave dinámica en las entregas más recientes del marco, pero que yo sepa, Java todavía no tiene algo similar.
Dicho esto, instanceof es generalmente mejor que comparar clases, ya que admitirá la herencia correctamente. También puede usar métodos como isAssignableFrom y otros de la API reflexion. Si desea implementar algo como el despacho dinámico, puede hacerlo a través de la API de reflexión, pero tenga cuidado, será lento. Úselo con precaución, idealmente debe corregir la estructura de objetos y el diseño de su aplicación si puede.
Espero que esto ayude
fuente