¿Instanceof devuelve verdadero si es una instancia de un padre?

6 minutos de lectura

avatar de usuario de ikbal
ikbal

Tengo una clase Child que se extiende Parent.

Parent child = new Child();

if (child instanceof Parent){
    // Do something
}

¿Esto devuelve verdadero o falso, y por qué?

Avatar de usuario de Ozair Kafray
Ozair Kafray

, sería. ¿Y por qué no debería?

Porque child es de hecho una instancia de Parent. Si desea realizar una operación solo para un niño, debe verificar

if (child instanceof Child){
}

Sin embargo, debe recordar la siguiente declaración de Efectivo C++, de Scott Meyers:

“Cada vez que te encuentres escribiendo código del tipo “si el objeto es del tipo T1, entonces haz algo, pero si es del tipo T2, entonces haz otra cosa”, date una bofetada.

que creo que se aplica en este caso también. Si quieres hacer algo según el tipo de clase al que pertenezca el objeto al que se hace referencia, la siguiente estructura de código debería ayudarlo.

NOTA: No lo he compilado.

class Parent {
    public void doSomething() {
        System.out.println("I am the Parent, and I do as I like");
    }
}
 
class ChildA extends Parent {
    public void doSomething() {
        System.out.println("I am a child named A, but I have my own ways, different from Parent");
    }
}
 
class ChildB extends Parent {
    public void doSomething() {
        System.out.println("I am a child named B, but I have my own ways, different from my Parent and my siblings");
    }
}
 
public class Polymorphism101 {
 
    public static void main(String[] args) {
 
        Parent p = new Parent();
        p.doSomething();
 
        p = new ChildA();
        p.doSomething();
 
        p = new ChildB();
        p.doSomething();
 
    }
 
}

EDITAR: Un mejor ejemplo

Podrías estar desarrollando un dibujo solicitud. Una aplicación que dibuja formas de cualquier tipo. En ese caso, debe tener un resumen escribe Shape.

Para propósitos como; dibujar todas las formas; enumere todas las formas; encontrar una forma o eliminar una forma, necesita tener un lista de Formas. Dado que la lista es de tipo principal, puede almacenar cualquier forma.

los Shape interfaz/clase abstracta/clase virtual debería tener un abstracto/puro virtual función Draw(). Entonces, en su DrawToDeviceLoop, simplemente llame Draw() para cada forma, nunca necesita verificar qué forma es.

los Shape La interfaz puede tener un resumen implementación AbstractShapeque puede tener un nombre de forma o una identificación como miembros de datos y GetName, Cleanup y otras funciones con funcionalidad común a todas las formas.

Recuerda un tipo abstracto no poder ser instanciado, por lo que Shape en sí mismo no puede ser instanciado, como tampoco puede ser dibujado.

EDIT 2: polimorfismo y manejo de excepciones – El usuario 1955934 preguntó “¿Qué pasa con la verificación de la clase de excepción?” Para el manejo de excepciones, las mejores prácticas con respecto al polimorfismo son:

  1. Preferir (lanzar) una excepción específica: por ejemplo, lanzar una NumberFormatException en lugar de IllegalArgumentException
  2. Detecte primero la excepción más específica: por ejemplo, si detecta primero una excepción IllegalArgumentException, nunca llegará al bloque catch que debería manejar la excepción NumberFormatException más específica porque es una subclase de IllegalArgumentException.

Entonces, básicamente es lo mismo, si una excepción necesita ser manejada de manera diferente, se debe definir una clase secundaria/específica, y la excepción específica debe ser capturado (instancia no marcada de)

Para conocer más prácticas recomendadas sobre el manejo de excepciones. Ver 9 mejores prácticas para manejar excepciones en Java y Mejores prácticas para excepciones (C#)

EDIT 3: Admito una excepción en esta regla

Entonces, estoy trabajando con un código heredado (escrito en C ++), que en su mayoría se escribió hace unos 15 años, donde siempre verifican que la clase secundaria realice ciertas acciones. Me pidieron que agregara un código con la misma lógica, y le dije a mi gerente (él también es un desarrollador) que no puedo hacer esto, señalé esta respuesta, y luego discutimos y aceptamos esta excepción a la regla. En nuestro caso, esta clase principal ha tenido solo 2 hijos desde el año 2000, y no vemos que se agregue ningún hijo en el futuro cercano, con el código central limitado para el crecimiento, decidimos que sin adición a las clases secundarias y actual siendo el número solo 2, es más eficiente verificar el tipo, especialmente cuando así es como se ha escrito el código, desde siempre.

Sin embargo, tampoco hay muchas instancias de esta verificación, el padre implementa principalmente las funcionalidades complicadas y existe más para compartir código que para especializarlas/diferenciarlas.

  • pero determino el tipo de objeto en tiempo de ejecución y necesito definir una referencia principal para contener todos los tipos de niños. ¿Cómo puedo hacer eso de otra manera?

    – ikbal

    10 de junio de 2011 a las 9:12

  • @user479129: puede mantener una referencia a cualquiera de los hijos de un padre en una referencia de tipo padre. Eso es si hay un class Parent {} y class ChildA extends Parent y class ChildB extends Parent entonces puedes usar Parent p para referirse a un objeto de tipo ChildA o ChildBpero no entiendo a qué te refieres con lo contrario.

    –Ozair Kafray

    10 de junio de 2011 a las 9:48

  • Necesito controlar que el objeto p sea un tipo de su hijo, no el padre. en algunos casos, puede ser el tipo principal, por lo que debo verificar que sea exactamente el tipo que quiero. eso es lo que quiero. espero que quede claro

    – ikbal

    10 de junio de 2011 a las 11:36

  • También me gustaría una respuesta mejorada, esto sería útil para trabajar con Frame.getComponents() en lugar de manejar cada uno individualmente.

    – Jason K.

    22 de febrero de 2017 a las 8:18

  • @JasonK. ¿Te refieres a un mejor ejemplo?

    –Ozair Kafray

    23 de febrero de 2017 a las 5:42

en vez de devolverá verdadero si es una subclase…

instancia de Documentación

  • Y ahora, esta pregunta siempre es cierta. Gracias

    – Nguyên Ngô Duy

    27 de agosto de 2020 a las 7:06

por supuesto, devuelve verdadero porque el niño es una instancia del padre

  • Sí, java any devuelve verdadero si el niño es una instancia del padre (o implemento).

    – Nguyên Ngô Duy

    27 de agosto de 2020 a las 7:05


Avatar de usuario de Roland
roland

. instanceof será verdadero siempre que la referencia (lado izquierdo de la instanceof expresión) se puede convertir a la Tipo de referencia(el tipo en el lado derecho de la instanceof expresión). Esto será cierto para las subclases en relación con su padre:

Child child = new Child();
Parent parent = (Parent) child; //works!
assert child instanceof Parent; //true

De La especificación del lenguaje Java, edición Java SE 9:

15.20. Operadores relacionales


ExpresiónRelacional en vez de Tipo de referencia

15.20.2. Operador de comparación de tipos


En tiempo de ejecución, el resultado de la instanceof el operador es true si el valor de la ExpresiónRelacional no es null y la referencia podría ser echada a la Tipo de referencia sin levantar un ClassCastException. De lo contrario el resultado es false.

¿Ha sido útil esta solución?