2013-03-27 2 views
32

Come posso chiamare il metodo mangia e bibita della classe Animal con l'istanza myAnimal nel codice?Come chiamare il metodo sovrascritto di una superclasse

public class Animal { 
    public void eat() { 
     System.out.println("Animal Eats"); 
    } 

    public void drink() { 
     System.out.println("Animal Drinks"); 
    } 
} 

public class Cat extends Animal { 
    @Override 
    public void eat() { 
     System.out.println("Cat Eats"); 
    } 

    @Override 
    public void drink() { 
     System.out.println("Cat Drinks"); 
    } 

    public static void main(String[] args) { 
     Cat myCat = new Cat(); 
     myCat.eat(); 
     myCat.drink(); 

     Animal myAnimal = myCat;   
     myAnimal.eat(); 
     myAnimal.drink(); 
    } 
} 

uscita che sto ottenendo:

Cat Eats 
Cat Drinks 
Cat Eats 
Cat Drinks 

Questo è il mio risultato atteso:

Cat Eats 
Cat Drinks 
Animal Eats 
Animal Drinks 
+1

Si desidera chiamare il 'animal' implementazione ** ** senza l'implementazione 'cat'? – mthmulders

+4

A meno che tu non abbia un metodo in 'Cat' witch chiama' super.eat(); 'non puoi farlo direttamente da' Cat' – A4L

+0

Non devi aspettarti quello che ti aspetti ... non dovrebbe entrambi in termini di la definizione della lingua e in termini di ciò che è ragionevole o desiderabile desiderare. L'intero punto del polimorfismo dell'ereditarietà è ottenere quello che stai vedendo e non quello che dici che ti aspetti. –

risposta

55

Non puoi fare quello che vuoi. Il modo in cui il polimorfismo funziona è facendo ciò che stai vedendo.

Fondamentalmente un gatto sa sempre che è un gatto e si comporta sempre come un gatto, indipendentemente dal fatto che si tratti di un gatto, Felis, Felinae, Felidae, Feliformia, Carnivora, Theria, Mammalia, Vertebrata, Cordata, Eumetazoa, Animalia, animali, oggetti, o qualsiasi altra cosa :-)

+2

Ne sei sicuro? –

+1

100% sicuro dato il codice che si desidera scrivere. Pubblicherò un'altra risposta che ti permetterà di fare ciò che stai cercando di fare, ma non sarà quello che vuoi fare ... – TofuBeer

+0

Ho lanciato Reflection su questo thread – WeMakeSoftware

5

Questa linea:

Animal myAnimal = myCat;

assegna la variabile myAnimal all'oggetto myCat, che hai creato in precedenza. Quindi, quando chiami lo myAnimal.eat(), in realtà stai chiamando il metodo dell'oggetto myCat originale, che emette Cat Eats.

Se si desidera emettere Animal Eats, sarà necessario assegnare un'istanza Animal a una variabile. Quindi, se volete fare questo, invece:

Animal myAnimal = new Animal()

il myAnimal variabile sarà un'istanza di Animal, e, quindi, sovrascriverà la precedente assegnazione a Cat.

Se si chiamerà myAnimal.eat() dopo questo, si sta effettivamente chiamando il metodo dell'istanza Animaleat() che hai creato, che sarà in uscita Animal Eats.

Concludendo: il codice dovrebbe leggere:

public class Cat extends Animal { 

    @Override 
    public void eat() { 
     System.out.println("Cat Eats"); 
    } 

    @Override 
    public void drink() { 
     System.out.println("Cat Drinks"); 
    } 

    public static void main(String[] args) { 
     Cat myCat = new Cat(); 
     myCat.eat(); 
     myCat.drink(); 

     Animal myAnimal = new Animal();   
     myAnimal.eat(); 
     myAnimal.drink(); 
    } 
} 
-1

Si prega di non votare su questa risposta ... si possono votare l'altro :-) Questa è una risposta cattiva, ma mostra come si farebbe fai quello che stai cercando di fare ... male.

+3

Se ammetti che è una cattiva risposta e non dovrebbe essere usato, probabilmente è meglio eliminarlo. – Rob

+2

Non proprio, è lì per mostrare alla gente cosa non fare. Chiunque può inventare questo, volevo far sapere alla gente che se lo facessero, allora dovrebbero buttarlo via. Da qui la mia richiesta di non votare affatto ... – TofuBeer

+5

Penso che sarebbe meglio se questa fosse una sezione della risposta accettata. –

0

Cat non può smettere di essere un gatto, anche se è un animale. Il gatto mangerà e il gatto berrà alla maniera di un gatto. Potrebbe essere simile a ciò che fa un animale, motivo per cui ha la precedenza sul metodo. Se vuoi che faccia ciò che l'animale fa per impostazione predefinita, non eseguire l'override. Si potrebbe forse fare un po 'cose strane con la riflessione e fare metodi separati che accedono ai metodi generali come:

public void superDrink() { 
    Animal.class.getMethod("drink").invoke(); 
} 

ma che potrebbe essere eccessivo non ti pare?

Certo che probabilmente non funzionerebbe visto che non è statico.

+0

java.lang.NoSuchMethodException –

16

Qui avrete la possibilità di scegliere quale metodo si vuole invocare:

public class Cat extends Animal { 

    public void superEat() { 
     super.eat(); 
    } 

    public void superDrink() { 
     super.drink(); 
    } 

    @Override 
    public void eat() { 
     System.out.println("Cat Eats"); 
    } 

    @Override 
    public void drink() { 
     System.out.println("Cat Drinks"); 
    } 
} 
1

Se fate i metodi di ciascuna classe statica, dovrebbe funzionare.

public class Animal { 
    public static void eat() { 
     System.out.println("Animal Eats"); 
    } 

    public static void drink() { 
     System.out.println("Animal Drinks"); 
    } 
} 


public class Cat extends Animal { 
    @Override 
    public static void eat() { 
     System.out.println("Cat Eats"); 
    } 

    @Override 
    public static void drink() { 
     System.out.println("Cat Drinks"); 
    } 

    public static void main(String[] args) { 
     Cat myCat = new Cat(); 
     myCat.eat(); 
     myCat.drink(); 

     Animal myAnimal = myCat;   
     myAnimal.eat(); 
     myAnimal.drink(); 
    } 
} 

Il codice qui sopra darà il seguente risultato

Cat Eats 
Cat Drinks 
Animal Eats 
Animal Drinks 
+4

Non penso che questo sia ciò che l'OP sta chiedendo, vuole essere in grado di accedere al metodo sottoposto a override in un oggetto istanziato, vorrei fare qualcos'altro come ridisegnare gli oggetti se questo è ciò che lui sta richiedendo – Goodwine

2

È possibile creare di costruzione per animali di classe, che prende un altro Animas come parametro e crea nuova istanza sulla base di una condizione.

public class Animal { 
    //some common animal's properties 
    private int weight; 
    private int age; 

    public Animal() { 
     // empty. 
    } 

    public Animal(final Animal otherAnimal) { 
     this.weight = otherAnimal.getWeight(); 
     this.age = otherAnimal.getAge(); 
    } 

    public void eat() { 
     System.out.println("Animal Eats"); 
    } 

    public void drink() { 
     System.out.println("Animal Drinks"); 
    } 

    // setters and getters. 
} 

public class Cat extends Animal { 
    @Override 
    public void eat() { 
     System.out.println("Cat Eats"); 
    } 

    @Override 
    public void drink() { 
     System.out.println("Cat Drinks"); 
    } 

    public static void main(String[] args) { 
     Cat myCat = new Cat(); 
     myCat.eat(); 
     myCat.drink(); 

     // note: myAnimal is not a Cat, it's just an Animal. 
     Animal myAnimal = new Animal(myCat);   
     myAnimal.eat(); 
     myAnimal.drink(); 
    } 
} 
+1

Questo è noto come "slicing" in C++; "affetti" la parte genitrice di un gatto per produrre un animale che non è più un gatto. Succede in C++ usando la sintassi simile alla sintassi dell'OP. In Java, devi farlo esplicitamente. Si noti che questo è un miglioramento, l'affettatura accidentale fa davvero schifo. – Yakk

2
  • accesso ai campi statici, campi istanza e metodi statici dipende dalla classe di riferimento variabile e non l'oggetto effettivo cui i punti variabili per.
  • Ricordare che le variabili membro sono ombreggiate, non sovrascritte.
  • Questo è l'opposto di ciò che accade nel caso dei metodi di istanza.
    In caso di metodi di istanza viene chiamato il metodo della classe effettiva dell'oggetto.

    class ABCD { 
        int x = 10; 
        static int y = 20; 
    
        public String getName() { 
         return "ABCD"; 
        } 
    } 
    
    class MNOP extends ABCD { 
        int x = 30; 
        static int y = 40; 
    
        public String getName() { 
         return "MNOP"; 
        } 
    } 
    
    public static void main(String[] args) { 
    
        System.out.println(new MNOP().x + ", " + new MNOP().y); 
    
        ABCD a = new MNOP(); 
        System.out.println(a.x); // 10 
        System.out.println(a.y); // 20 
        System.out.println(a.getName()); // MNOP 
    } 
    

In questo esempio, anche se l'mycat l'oggetto è assegnato a un riferimento a un oggetto di animale, (Animal myAnimal = myCat) l'oggetto reale è di tipo Cat e si comporta come un gatto.

Spero che questo aiuti.

0

alcuni suggerimenti:

  1. non passano di riferimento classe figlio alla classe super e ad eccezione di metodo di classe Super deve essere invocata per il metodo di override. Chiama i metodi di super classe dall'istanza di super classe.

    Animal myAnimal = new Animal(); 
    myAnimal.eat(); 
    
  2. Se si desidera chiamare il metodo super-classe da classe figlia, chiamare in modo esplicito eccellente nome del metodo classe con super.methodName();

    public void eat() { 
        super.eat(); 
        System.out.println("Cat Eats"); 
    } 
    
  3. Non sovrascrivere il metodo di super classe in classe figlio. Viene invocato sempre il metodo super-classe.
0
public class Main { 
    public static void main(String[] args) { 
     Cat myCat = new Cat(); 
     myCat.eat(); 
     myCat.drink(); 

     Animal myAnimal = new Animal(); 
     myAnimal.eat(); 
     myAnimal.drink(); 
    } 
} 

public class Animal { 
    public void eat(){ 
     System.out.println("Animal eat() called"); 
    } 
    public void drink(){ 
     System.out.println("Animal drink() called"); 
    } 
} 

public class Cat extends Animal { 
    @Override 
    public void eat() { 
     System.out.println("Cat eat() called"); 
    } 

    @Override 
    public void drink() { 
     System.out.println("cat drink() called"); 
    } 
} 

USCITA:

Cat mangiare() chiamato

bevanda gatto() chiamato

Animal mangiare() chiamato

bevanda degli animali() chiamato

È necessario creare un oggetto della classe super-Animal o un'altra opzione è quella di utilizzare la parola chiave super nei metodi della classe bambino per esempio, super.eat() o super.drink()