2009-05-22 8 views
14

animale è una superclasse di cane e cane ha un metodo chiamato cortecciaÈ possibile chiamare i metodi di sottoclassi su un oggetto superclasse?

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

Si consideri il seguente:

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

Che cosa accadrà?

  1. l'assegnazione non è consentito
  2. la chiamata alla corteccia è consentito e "bau" è stampato in fase di esecuzione
  3. la chiamata alla corteccia è consentito, ma non viene stampato nulla
  4. la chiamata ad abbaiare causa un errore di compilazione
  5. la chiamata ai risultati corteccia in un errore di tempo di esecuzione

ho detto 2 come stiamo verificando se l'oggetto è un cane; come cane è la classe con il metodo della corteccia in esso, se è allora lo chiamiamo che stamperà: s

La mia comprensione è corretta qui?

+0

suggerisce di cambiare la domanda qui "Le superclassi hanno i metodi delle loro sottoclassi?" o simili. –

+1

Il trucco sta nel fatto che stai verificando che si tratti di un cane, ma il compilatore non stabilisce la connessione logica che a.bark verrà chiamata solo se a è un cane. Dovresti dire esplicitamente al compilatore di trattare un Like a Dog ai fini della chiamata alla bark(), come detto in seguito da Simon622. –

+1

Per inciso, questo è il motivo per cui molte persone preferiscono "battere a macchina". In Python, il codice equivalente non avrebbe nemmeno bisogno di controllare se 'a' fosse un cane; Finché 'a' aveva un metodo' bark' quando veniva raggiunta quella linea, avrebbe funzionato. –

risposta

31

Questo non verrà compilato poiché Animal non ha un metodo chiamato corteccia. Pensaci in questo modo, tutti i cani sono animali, ma non tutti gli animali sono cani. Tutti i cani abbaiano, ma non tutti gli animali abbaiano.

+6

E quindi, 4 è la risposta corretta . –

25

no - la risposta è;

4) la chiamata corteccia provoca una fase di compilazione errore

metodo corteccia è neanche definita come metodo sull'animale tipo assegnato, che quindi tradurrà in questione fase di compilazione; questo potrebbe essere risolto mediante casting;

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

È 4. Non si può chiedere ad un animale generico, che è quello che dice il codice, abbaiare. Perché si potrebbe facilmente dire

Animal a = new Cat(); 

e la linea di corteccia non ha un modo per sapere che non l'hai fatto.

11

La chiave è nella riga seguente:

Animal a = new Dog(); 

Sebbene una nuova istanza di Dog stato creato, il riferimento è da a che è dichiarato essere di tipo Animal. Pertanto, qualsiasi riferimento a a fa sì che new Dog venga gestito come Animal.

Pertanto, a meno che Animal ha un metodo bark, la seguente riga causerà un errore di compilazione:

a.bark(); 

Anche se a viene testato per vedere se è un'istanza di Dog e a instanceof Dog restituisce effettivamente true , la variabile a è di tipo Animal, quindi il blocco all'interno dell'istruzione if gestisce ancora a come Animal.

Questa è una funzionalità di statically-typed languages in cui alle variabili viene assegnato un tipo prima del tempo e controllato in fase di compilazione per verificare che i tipi corrispondano. Se questo codice sono stati eseguiti su un dynamically-typed language, dove i tipi vengono controllati in fase di esecuzione, qualcosa di simile al seguente potrebbe essere consentito:

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

a.bark() è garantita solo da eseguire quando l'istanza è una Dog, quindi la chiamata a bark funzionerà sempre Tuttavia, Java è un linguaggio tipizzato staticamente, quindi questo tipo di codice non è permesso.

+0

+1 per aggiungere la spiegazione re: staticamente- vs lingue digitate dinamicamente. –

+0

Cosa succede se entrambe le classi hanno il metodo bark(), quale viene eseguito. –

+1

@Rahul Kadukar: se "** animale ** è una superclasse di ** cane **", ed entrambe le classi hanno il metodo ** bark() **, allora ** bark() ** è sovrascritto al * * metodo bark() ** nella sottoclasse ** cane **. Pertanto, a.bark() eseguirà il metodo ** bark() ** nella classe ** dog **. – NoName

3

In Head First Java usano la molto buona analogia di un telecomando TV per un di riferimento e il televisore come l'oggetto che i punti di riferimento per. Se il tuo telecomando ha solo i pulsanti (metodi) per on, off, channel up e down, e volume su e giù, non importa quali sono le funzioni interessanti della tua TV. Puoi ancora solo fare quelle poche cose di base dal tuo telecomando. Non è possibile disattivare l'audio della TV, ad esempio, se il telecomando non ha un pulsante di disattivazione dell'audio.

Il riferimento Animal conosce solo i metodi Animal. Non importa quali altri metodi ha l'oggetto sottostante, non puoi accedervi da un riferimento Animale.

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"

La tua motivazione è corretta, ma non è così che funziona.

Java è un linguaggio tipizzato statico che significa che la validità dei metodi a cui un oggetto può rispondere è verificata al tempo di compilazione.

si potrebbe pensare il controllo:

if(a instanceof Dog) 

farebbe, ma in realtà non è così. Che cosa fa il compilatore è controllare contro "l'interfaccia" del tipo dichiarato (Animale in questo caso). L '"interfaccia" è composta dai metodi dichiarati nella classe Animal.

Se il metodo dicorteccia() non è definito nella classe Super animali il compilatore dice: "Ehi, che non funzionerà".

Questo è utile, perché "a volte" facciamo errori di battitura durante la codifica (digitando Barck(), invece, per esempio)

Se il compilatore non non ci avverte di questo, si dovrebbe trovare in " runtime "e non sempre con un messaggio chiaro (ad esempio javascript in IE dice qualcosa come" oggetto inatteso ")

Ancora, il linguaggio tipizzato statico come java ci consente di forzare la chiamata. In questo caso si sta usando l'operatore "cast"()

Ti piace questa

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

In linea 3 vostro stanno "casting" per un tipo di cane in modo che il compilatore può controllare se la corteccia è un messaggio valido.

Questa è un'istruzione al compilatore che dice "Ehi sono il programmatore qui, so cosa sto facendo". E il compilatore, controlla, Ok, cane, può ricevere il messaggio abbaiare(), procedere. Tuttavia, se in runtime l'animale non è un cane, si verificherà un'eccezione di runtime.

Il cast potrebbe anche essere abbreviato come:

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

che verrà eseguito.

Quindi, la risposta corretta è 4: "la chiamata ad abbaiare causa un errore di compilazione"

Spero che questo aiuta.

2

FYI, questo non è un buon progetto.

Quasi ogni volta che si ha il codice di questa forma:

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

si sta abusando il sistema di tipi. Questo non è il modo di usare le classi, non è il modo di scrivere codice orientato agli oggetti gestibile. È fragile È contorto. È cattivo.

È possibile creare metodi di template in una classe base, ma devono chiamare metodi che esistono nella classe base e sono sovrascritti nelle sottoclassi.

4

Se l'idea è quella di stampare il metodo della sottoclasse dall'oggetto superclasse, questo funziona:

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

Animal a = new Dog(); 

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

Questo getta la superclasse di nuovo a sottoclasse e lo stampa. nonostante il suo cattivo design, è il suo unico modo per sapere quale classe figlio si rivolge a dinamicamente.

+0

Oppure, se devi fare qualcosa del genere, potresti fare 'if (a instanceof Dog) {((Dog) a) .bark(); } ' – GreenMatt

2

In java (solo lingua che conosco) è possibile creare un metodo vuoto e chiamarlo in super classe. Quindi puoi eseguirne l'override in sottoclasse per fare quello che vuoi. In questo modo la super classe chiama il suo metodo di sottoclasse.

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(){ 
    } 
} 

Questo codice chiama un oggetto di Snake quindi chiama un oggetto di Cane.E scrive questo per console:

this animal can't bark 
Woof 

Snake non ha alcun metodo corteccia così il metodo super-class' è chiamato. Scrive la prima riga sulla console. Il cane ha un metodo di abbaio, quindi la super classe lo chiama. Scrive la seconda riga sulla console.