È ansible chiamare i metodi di sottoclassi su un object superclass?

L’animale è una superclass di cane e cane ha un metodo chiamato corteccia

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

Considera quanto segue:

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

Cosa accadrà?

  1. il compito non è permesso
  2. la chiamata ad abbaiare è consentita e “woof” viene stampato in fase di esecuzione
  3. la chiamata ad abbaiare è consentita ma non viene stampato nulla
  4. la chiamata ad abbaiare causa un errore in fase di compilazione
  5. la chiamata ad abbaiare risulta in un errore di runtime

Ho detto 2 mentre stiamo controllando se l’object è un cane; come cane è la class con il metodo della corteccia in esso, se è allora lo chiamiamo che stamperà: s

La mia comprensione è corretta qui?

    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.

    no – la risposta è;

    4) la chiamata a corteccia causa un errore di compilazione

    il metodo di abbaio non è definito come un metodo sul tipo assegnato Animale, che pertanto risulterà in un problema di tempo di compilazione; questo potrebbe essere risolto mediante casting;

     ((Dog)a).bark(); 

    La chiave è nella seguente riga:

     Animal a = new Dog(); 

    Sebbene sia stata creata una nuova istanza di Dog , il suo riferimento è quello che è dichiarato essere del tipo Animal . Pertanto, ogni riferimento a a new Dog essere gestito come un Animal .

    Pertanto, a meno che Animal non abbia un metodo di bark , la seguente riga causerà un errore del compilatore:

     a.bark(); 

    Anche se viene testato per vedere se si tratta di un’istanza di Dog e a instanceof Dog restituirà effettivamente true , la variabile a è ancora di è di tipo Animal , quindi il blocco all’interno a instanceof Dog if continua a gestirlo come un Animal .

    Questa è una funzionalità di linguaggi tipizzati staticamente in cui le variabili vengono assegnate in anticipo di un tipo e controllate in fase di compilazione per verificare che i tipi corrispondano. Se questo codice è stato eseguito su un linguaggio tipizzato in modo dinamico , in cui i tipi vengono controllati in fase di runtime, è ansible che sia consentito quanto segue:

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

    a.bark() è garantito solo per l’esecuzione quando l’istanza è un Dog , quindi la chiamata ad bark funzionerà sempre. Tuttavia, Java è un linguaggio tipizzato staticamente, quindi questo tipo di codice non è permesso.

    In Head First Java usano l’ottima analogia di un telecomando TV come riferimento e il televisore come l’ object a cui punta il riferimento. 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 è ansible distriggersre l’audio della TV, ad esempio, se il telecomando non ha un pulsante di distriggerszione dell’audio.

    La referenza Animal conosce solo i metodi Animal. Non importa quali altri metodi ha l’object sottostante, non puoi accedervi da un riferimento Animale.

    È 4. Non puoi chiedere ad un animale generico – che è quello che dice il tuo codice – abbaiare. Perché avresti potuto facilmente dire

     Animal a = new Cat(); 

    e la linea della corteccia non ha modo di sapere che non l’hai fatto.

    Se l’idea è di stampare il metodo della sottoclass dall’object superclass, questo funzionerà:

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

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

    Questo proietta la superclass nella sottoclass e la stampa. nonostante il suo cattivo design, il suo unico modo per sapere quale class di bambino si oppone al suo puntamento dynamicmente.

    Cordiali saluti, questo non è un buon progetto.

    Quasi ogni volta che hai il codice di questo modulo:

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

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

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

    In java (solo la lingua che conosco) puoi creare un metodo vuoto e chiamarlo in super-class. Quindi puoi eseguirne l’override in sottoclass per fare quello che vuoi. In questo modo la super class chiama il suo metodo di sottoclass.

     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 object di Snake quindi chiama un object di Cane. Scrive questo per console:

     this animal can't bark Woof 

    Snake non ha alcun metodo di abbaiare per cui viene chiamato il metodo di super-class. Scrive la prima riga sulla console. Il cane ha un metodo di abbaio, quindi la super class lo chiama. Scrive la seconda riga sulla console.

    “Ho detto 2 mentre stiamo controllando se l’object è un cane, come il cane è la class con il metodo della corteccia in esso, se è quindi lo chiamiamo che stamperà: 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 object può rispondere è verificata in fase di compilazione .

    Potresti pensare al controllo:

     if( a instanceof Dog ) 

    Lo farebbe, ma in realtà no. Che cosa fa il compilatore è controllare contro “l’interfaccia” del tipo dichiarato (Animale in questo caso). L ‘”interfaccia” è composta dai metodi dichiarati nella class Animal.

    Se il metodo bark () non è definito nella super class Animal, il compilatore dice: “Ehi, non funzionerà”.

    Questo è utile, perché “a volte” facciamo errori durante la codifica (digitando invece barck () per esempio)

    Se il compilatore non ci avvisa di ciò, dovresti trovarlo su “runtime” e non sempre con un messaggio chiaro (ad esempio javascript in IE dice qualcosa come “object inatteso”)

    Tuttavia, il linguaggio tipizzato statico come java ci consente di forzare la chiamata. In questo caso sta usando l’operatore “cast” ()

    Come questo

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

    Nella riga 3 si “lancia” su un tipo di Cane in modo che il compilatore possa 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(); } 

    Ciò funzionerà.

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

    Spero che aiuti.