2009-05-22 17 views
14

animal es una superclase de perro y perro tiene un método llamado corteza¿Es posible llamar a los métodos de las subclases en un objeto de superclase?

public void bark() 
{ 
    System.out.println("woof"); 
} 

considerar lo siguiente:

Animal a = new Dog(); 
if (a instanceof Dog){ 
    a.bark(); 
} 

¿Qué pasará?

  1. la asignación no está permitido
  2. se permite la llamada a la corteza y "trama" se imprime en tiempo de ejecución
  3. la llamada a la corteza está permitido, pero no se imprime nada
  4. la llamada a la corteza provoca un error de tiempo de compilación
  5. la llamada a los resultados de corteza en un error de tiempo de ejecución

dije 2 como estamos comprobando si el objeto es un perro; como perro es la clase con el método de corte en él, si es así lo llamamos que se imprimirá: s

¿Es correcto mi entendimiento aquí?

+0

sugieren cambiar la pregunta aquí a "hacer superclases tienen los métodos de sus subclases?" o similar. –

+1

El truco es que está comprobando para asegurarse de que es un perro, pero el compilador no establece la conexión lógica de que a.bark solo se llamará si a es un perro. Tendría que decirle explícitamente al compilador que trate a un Perro como para la llamada a ladrar(), como Simon622 dice a continuación. –

+1

Dicho sea de paso, esta es la razón por la que muchas personas prefieren "escribir patos". En, por ejemplo, Python, el código equivalente ni siquiera necesitaría verificar si 'a' era un perro; siempre que 'a' tenga un método' ladrido' cuando se llegue a esa línea, funcionaría. –

Respuesta

31

Esto no compilará ya que Animal no tiene un método llamado corteza. Piénselo de esta manera, todos los perros son animales, pero no todos los animales son perros. Todos los perros ladran, pero no todos los animales ladran.

+6

Y así, 4 es la respuesta correcta . –

25

no - la respuesta es;

4) la llamada a la corteza provoca un tiempo de compilación error

la tampoco método corteza definido como un método del tipo asignado animal, por lo tanto, lo que resultará en cuestión tiempo de compilación; esto podría resolverse mediante casting;

((Dog)a).bark(); 
4

Es 4. No puede pedirle a un Animal genérico, que es lo que su código dice que es, ladrar. Porque podría haber dicho tan fácilmente

Animal a = new Cat(); 

y la línea de corte no tiene una forma de saber que usted no lo hizo.

11

la llave está en la línea siguiente:

Animal a = new Dog(); 

Aunque se ha creado una nueva instancia de Dog, su referencia es por a que se declara a ser del tipo Animal. Por lo tanto, cualquier referencia a a hace que el new Dog se maneje como Animal.

Por lo tanto, a menos que Animal tiene un método bark, la siguiente línea provocará un error de compilación:

a.bark(); 

Aunque a se prueba para ver si es una instancia de Dog y a instanceof Dog realidad volverá true , la variable a es de tipo Animal, por lo que el bloque dentro de la declaración if todavía maneja a como Animal.

Esta es una característica de statically-typed languages donde las variables se asignan con un tipo de anticipación, y se comprueban en tiempo de compilación para ver que los tipos coinciden. Si este código se llevaron a cabo en un dynamically-typed language, donde los tipos se comprueban en tiempo de ejecución, algo como lo siguiente podía permitir:

var a = new Dog(); 
if (a instanceof Dog) 
    a.bark(); 

a.bark() solamente está garantizada a ejecutar cuando la instancia es un Dog, por lo que la llamada a bark siempre funcionará Sin embargo, Java es un lenguaje de tipo estático, por lo que este tipo de código no está permitido.

+0

+1 para agregar la explicación a: lenguajes estáticos vs. dinámicos. –

+0

¿Qué sucede si ambas clases tienen el método bark(), cuál se ejecuta? –

+1

@Rahul Kadukar: Si "** ** animales es una superclase de perro ** **", y ambas clases tienen la corteza **() ** método, entonces ** corteza() ** se anula a la * * método de ladrido() ** en la subclase ** perro **. Por lo tanto, a.bark() ejecutará el método ** bark() ** en la clase ** dog **. – NoName

3

En Head First Java Utilizan la muy buena analogía de un mando a distancia del televisor para una referenciay el televisor como el objeto de que los puntos de referencia a. Si su control remoto solo tiene botones (métodos) para activar, desactivar, subir y bajar canales y subir y bajar el volumen, no importa las características geniales que tenga su televisor. Todavía puede hacer esas pocas cosas básicas desde su control remoto. No puede silenciar su televisor, por ejemplo, si su control remoto no tiene botón de silencio.

La referencia de Animal solo conoce los métodos de Animal. No importa qué otros métodos tenga el objeto subyacente, no puede acceder a ellos desde una referencia Animal.

1

"I said 2 as we are checking if the object is a dog; as dog is the class with the bark method in it, if it is then we call it which will print out :s"

Su razonamiento es correcto, pero esa no es la forma en que funciona.

Java es un lenguaje tipado estático que significa que la validez de los métodos a los que un objeto puede responder se verifica al tiempo de compilación.

Usted puede pensar que el cheque:

if(a instanceof Dog) 

haría, pero en realidad no es así. Lo que hace el compilador es comparar con la "interfaz" del tipo declarado (Animal en este caso). La "interfaz" se compone de los métodos declarados en la clase Animal.

Si el métodocorteza() no está definido en la superclase Animal el compilador dice: "Oye, eso no funcionará".

Esto es muy útil, ya que "a veces" hacemos errores tipográficos mientras que la codificación (barck (escribir) en lugar, por ejemplo)

Si el compilador no no nos advierten acerca de esto, tendría que encontrar en " runtime "y no siempre con un mensaje claro (por ejemplo javascript en IE dice algo así como" objeto inesperado ")

Aún así, el lenguaje estático mecanografiado como java nos permite forzar la llamada. En este caso se utiliza el operador "fundido"()

gusta esta

1. Animal a = new Dog(); 
2. if (a instanceof Dog){ 
3.  Dog imADog = (Dog) a; 
4.  imADog.bark(); 
5. } 

En la línea 3 de su son "casting" a un tipo de perro por lo que el compilador puede comprobar si la corteza es un mensaje válido.

Esta es una instrucción para el compilador que dice "Hola, soy el programador aquí, sé lo que estoy haciendo". Y el compilador, comprueba, Ok, perro, puede recibir el mensaje ladrido(), proceda. Sin embargo, si en tiempo de ejecución el animal no es un perro, se generará una excepción de tiempo de ejecución.

El reparto también podría abreviarse como:

if(a instanceof Dog) { 
    ((Dog)a).bark(); 
} 

que se ejecutarán.

Por lo tanto, la respuesta correcta es 4: "la llamada a la corteza provoca un error de tiempo de compilación"

espero que esto ayude.

2

FYI, este no es un buen diseño.

Casi cualquier momento que tenga código de este formulario:

if (x instanceof SomeClass) 
{ 
    x.SomeMethod(); 
} 

usted está abusando del sistema de tipos. Esta no es la manera de usar clases, no es la forma de escribir código orientado a objetos que se pueda mantener. Es quebradizo. Es complicado. Es malo.

Puede crear métodos de plantilla en una clase base, pero tienen que llamar a los métodos que existen en la clase base y se anulan en las subclases.

4

Si la idea es imprimir el método de la subclase de objeto superclase, esto va a funcionar:

En lugar de Animal a = new Dog(); if (a instanceof Dog){ a.bark(); } cambio a

Animal a = new Dog(); 

if (a instanceof Dog){ 
    Dog d = (Dog) a; 
    d.bark(); 
} 

Esto arroja la superclase de nuevo a la subclase y lo imprime. aunque es un mal diseño, es una forma de saber a qué clase de elemento infantil apunta de forma dinámica.

+0

O, si debe hacer algo como esto, podría hacer 'if (una instancia de Dog) {((Dog) a) .bark(); } ' – GreenMatt

2

En java (único idioma que conozco) puede crear un método vacío y llamarlo en super clase. Luego puede anularlo en la subclase para hacer lo que quiera. De esta forma, la superclase llama a su método de subclase.

public class Test { 
    public static void main(String[] args){ 
     Snake S = new Snake(); 
     Dog d = new Dog(); 
    } 
} 


class Animal{ //Super Class 
    public Animal(){ 
     bark(); //calls bark when a new animal is created 
    } 
    public void bark(){ 
     System.out.println("this animal can't bark"); 
    } 
} 



class Dog extends Animal{ //Subclass 1 
    @Override 
    public void bark(){ 
     System.out.println("Woof"); 
    } 
} 



class Snake extends Animal{//Subclass 2 
    public void tss(){ 
    } 
} 

Este código llama a un objeto de Serpiente y luego llama a un objeto de Perro.Se escribe esto a la consola:

this animal can't bark 
Woof 

serpiente no tiene ningún método corteza de lo que el método de superclase se llama. Escribe la primera línea en la consola. El perro tiene un método de ladrido, por lo que la súper clase lo llama en su lugar. Escribe la segunda línea a la consola.

Cuestiones relacionadas