¿Está usando la palabra clave instanceof
contra la esencia de object oriented programming
? Quiero decir, ¿es una mala práctica de programación? Leí en alguna parte que el uso de la palabra clave instanceof
significa que el diseño puede no ser tan bueno. ¿Alguna mejor solución?instancia del uso de la palabra clave
Respuesta
Hablando en general sí. Lo mejor es mantener todo el código que depende de ser una clase específica dentro de esa clase, y usar instanceof
generalmente significa que has puesto algún código fuera de esa clase.
mirada a este ejemplo muy simple:
public class Animal
{
}
public class Dog extends Animal
{
}
public class Cat extends Animal
{
}
public class SomeOtherClass
{
public abstract String speak(Animal a)
{
String word = "";
if (a instanceof Dog)
{
word = "woof";
}
else if (a instanceof Cat)
{
word = "miaow";
}
return word;
}
}
Idealmente, nos gustaría que todo el comportamiento que es específico para los perros que se encuentran en la clase de perro, en lugar de difusión en todo nuestro programa. Podemos cambiar eso reescribiendo nuestro programa como este:
public abstract class Animal
{
public String speak();
}
public class Dog extends Animal
{
public String speak()
{
return "woof";
}
}
public class Cat extends Animal
{
public String speak()
{
return "miaow";
}
}
public class SomeOtherClass
{
public String speak(Animal a)
{
return a.speak();
}
}
Hemos determinado que un Animal
tiene que tener un método speak
. Ahora, SomeOtherClass
no necesita conocer los detalles particulares de cada tipo de animal; puede entregarlo a la subclase Animal
.
Sólo como un extra punto: Como se dijo en esta respuesta, un problema con 'instanceof' es que necesita especificar el subtipo. ¿Qué pasa si los subtipos cambian? Entonces necesita volver a escribir las pruebas 'instanceof'. Pero si usa un enlace dinámico y un polimorfismo, no hará la diferencia y seguirá funcionando. – adamjmarkham
+1: Debido a la parte de "cómo se debe realmente hacer": D –
¿Debe 'hablar' ser' abstracto' en Animal, o todos los animales comienzan a silenciarse? –
Está desanimado porque la gente puede utilizar para hacer algo como esto:
if(myAnimal instanceof Dog)
((Dog)myAnimal).bark();
else(myAnimal instanceof Cat)
((Cat)myAnimal).meow();
En cambio, Animal
debe tener un método speak()
cuales Dog
y Cat
hereda. En programación orientada a objetos apropiada con el polimorfismo y la dinámica de unión, usted entonces sólo tiene que hacer
myAnimal.speak();
Sin embargo, hay algunos casos en los que se debe utilizar instanceof
para determinar el tipo específico de un objeto. Quizás tenga una lista de Animals
en su casa y los únicos que desee sacar por walk()
son Dog
s. En ese caso, recorrería su lista y solo walk()
los perros.
Me encanta el hecho de que estábamos escribiendo estos al mismo tiempo y ambos fueron para ejemplos de animales :) –
Estaba a punto de comentar exactamente lo mismo en su publicación al igual que usted comentó sobre el mío :) – tskuzzy
Favorece el polimorfismo y el enlace dinámico a la bajada y instanceof
. Esta es la "OO Way" y le permite escribir código que no necesita saber acerca de los subtipos.
Ejemplo
abstract class Animal {
public abstract void talk();
//...
}
class Dog extends Animal {
public void talk() {
System.out.println("Woof!");
}
//...
}
class Cat extends Animal {
public void talk() {
System.out.println("Meow!");
}
//...
}
class Hippopotamus extends Animal {
public void talk() {
System.out.println("Roar!");
}
//...
}
class Main {
public static void main(String[] args) {
makeItTalk(new Cat());
makeItTalk(new Dog());
makeItTalk(new Hippopotamus());
}
public static void makeItTalk(Animal animal) {
animal.talk();
}
}
Creo que 'abajo' sería un fonema más apropiado para un hipopótamo :). Voy a subclasificar y anular el comportamiento predeterminado. +1 para su diseño que me permite también. – Perception
Uso de instanceof
se desaconseja cuando mismo efecto se puede lograr a través de métodos virtuales, como en el ejemplo de thomson_matt. Sin embargo, es necesario utilizar instanceof
en algunas circunstancias. Por ejemplo, cuando su código obtiene un Objeto de una fuente externa, por ejemplo, API de red o de un tercero que devuelve Object
, debe decidir cuál es el tipo de este Objeto y actuar de forma adecuada.
Hay muchas buenas respuestas que promueven los métodos virtuales, pero instanceof
tiene su uso también. Imagine que itera sobre List<Event>
, para recoger todos los objetos Urgent
. Puede hacerlo usando isUrgent()
, pero no estoy seguro si fue necesariamente más conciso o legible.Además, isUrgent()
requeriría que Event
tenga en cuenta que sus subclases pueden poseer la propiedad respectiva, que podría:
Event
pertenece a alguna biblioteca que no se puede modificar.La clave es no ver instancias como parte de una "práctica normal" común. Al igual que la introspección en general, instanceof es una herramienta especial para usar en circunstancias atípicas particulares. Siempre que use 'instanceof', también puede encontrarse utilizando otras partes 'especiales' de la plataforma, como la reflexión en general.
Siempre y cuando te encuentres utilizándote aceptas que lo que estás haciendo es un desafío en ausencia de una alternativa más elegante/práctica, entonces está bien.
Dicho esto, las circunstancias más típicas de los programas de todos los días son probablemente:
- iguales de ejecución()
- lectura objetos serializados
- algunos otros casos en los que le den una serie/colección de artículos, por ejemplo enumerar JComponents en un marco/contenedor y luego tomar medidas dependiendo del tipo.
Una regla de oro que podría intentar y atenerse es no requerir que los usuarios de una biblioteca tengan que usar 'instanceof', sino que tengan casos de 'instancia de' internos en la biblioteca.
O dicho de otra manera, debe volver a enmarcar su pregunta: "¿Cuáles son los casos en que 'intsanceof' es una solución para?"
thomson_matt ha dado un buen ejemplo de mal uso de instanceof. Ahora tengo una situación, donde todas las condiciones que dijo, son ciertas. Say Animal es la clase abstracta, Cat y Dog son sus subclases. Entonces, naturalmente, el sonido que cada animal debería hacer debe ser encapsulado en su propia clase. Pero digamos que tengo otra clase llamada Mouse que reacciona a diferentes animales de diferentes maneras. Si se trata de un perro, el mouse no hace mucho más que evitar el camino del perro. Si es un gato, intenta esconderse. En tal situación, ¿está bien hacerlo? ¿Existe algún método mejor? – aps
Puede tener múltiples métodos reactTo (...) en el objeto Mouse, uno para cada tipo de animal, y pasar el animal al que desea que reaccione el mouse. –
¿Qué tal, en el caso de una fábrica de creación (consulte a continuación)? En este caso, no creo que sea apropiado que una subclase de Animal sepa cómo construir una jaula para sí misma. Parece estar fuera del alcance de lo que es un Animal y obliga a la subclase Animal a asumir comportamientos que no son intrínsecos a lo que es un Animal.
public static Cage createCage(Animal animal) {
if (animal instanceof Dog)
return new DogHouse();
else if (animal instanceof Lion)
return new SteelCage();
else if (animal instanceof Chicken)
return new ChickenWiredCage();
else if (animal instanceof AlienPreditor)
return new ForceFieldCage();
...
else
return new GenericCage();
}
Otro uso del funcionamiento de instaceOf podría ser el manejo de errores. Si usted tiene el control de errores similar para excepciones, y que desea tener todo en un solo lugar se puede usar:
public void handleError(Throwable t, HttpServletRequest req) {
if (t instaceOf ValidationException) {
...doSomewthing......
} else if (t instaceOf DataException) {
...doSomewthing......
} else if (t instaceOf DataException) {
...doSomewthing......
} else {
...doSomewthing......
}
}
con el código de seguridad, se evita tener muchos
} catch <Exception> {
bloques y en lugar de tener sólo una
} catch (Throwable t) {
handleError(t, request);
return "errorPage" or whateveryouwant;
}
Además, es una cosa más, es revisar el código fuente de java, encontrará tantos usos de instaceof ..
Y un buen enlace: article about usage of instaceof
- 1. C# ref uso de la palabra clave
- 2. Uso práctico de la palabra clave `stackalloc`
- 3. el uso de la palabra clave privada
- 4. USO palabra clave en Mysql
- 5. Uso de la palabra clave de bloqueo C#
- 6. Uso de la palabra clave "this" en java
- 7. El uso de esta palabra clave Java
- 8. as3: uso de esta palabra clave
- 9. Uso realista de la palabra clave 'restringir' C99?
- 10. Ilustrando el uso de la palabra clave volátil en C#
- 11. Aprendizaje de Java, uso de la palabra clave sincronizada
- 12. C# Patrones de uso para la palabra clave "es"
- 13. C# utilizando la palabra clave, el uso adecuado de él
- 14. uso de la palabra clave "using" en C#
- 15. Uso práctico de la palabra clave parcial en C#
- 16. ¿Cuál es el uso de la palabra clave volátil?
- 17. Uso de la palabra clave auto en C STL ++
- 18. Uso de la palabra clave "global" en Python
- 19. ¿Cuál es el uso de la palabra clave final?
- 20. Escriba palabra clave en clase y declaraciones de instancia
- 21. Acerca de la palabra clave de `self`
- 22. ¿Cómo uso programáticamente la palabra clave "usar" en C#?
- 23. ¿Este ejemplo del uso de la palabra clave "explícita" de C++ es correcto?
- 24. palabra clave privada vs no palabra clave privada
- 25. C: Comportamiento de la palabra clave `const`
- 26. ¿Cómo uso la palabra clave del número de revisión global con TortoiseSVN?
- 27. ¿La palabra clave "var" dificulta la legibilidad del código?
- 28. Scala: palabra clave como nombre del paquete
- 29. Palabra clave "foreach" inesperada después del carácter "@"
- 30. ¿Cómo uso una palabra clave C# como nombre de propiedad?
¿Cuál es la instancia en la que lo está utilizando? Es difícil proporcionar una solución si el problema no aparece en la lista. – Kal
@aps ¿puede mostrar el uso de 'instanceof' que le preocupa? –
No lo estoy usando. Pero solo pregunto por qué no se considera una programación tan buena si alguien usa instanceof. – aps