2013-04-14 15 views
6

Ciao mi chiedo se c'è una semplice soluzione al mio problema,ArrayList contenente diversi oggetti dello stesso superclasse - come accedere metodo di una sottoclasse

Ho un ArrayList:

ArrayList <Animal> animalList = new ArrayList<Animal>(); 

/* I add some objects from subclasses of Animal */ 

animalList.add(new Reptile()); 
animalList.add(new Bird()); 
animalList.add(new Amphibian()); 

Tutti implementano un metodo move() - Il Bird vola quando viene chiamato move(). So che posso accedere a metodi e le proprietà della classe Super comuni utilizzando questo

public void feed(Integer animalIndex) { 
    Animal aAnimal = (Animal) this.animalList.get(animalIndex); 
    aAnimal.eat(); 
} 

va bene - ma ora vorrei accedere al metodo move() la sottoclasse Bird ha. ho potuto farlo lanciando il Animal come Bird:

Bird aBird = (Bird) this.animalList.get(animalIndex); 
aBird.move(); 

Nella mia situazione non voglio fare questo, perché vorrà dire che ho 3 diversi set di codice uno sopra per ogni sottotipo di Animal.

Sembra un po 'ridondante, c'è un modo migliore?

+3

perché non dovrebbe avere un animale 'mossa()' metodo che si ignorare nelle sottoclassi? –

+0

... Chiama mossa? Se non sta chiamando l'implementazione della sottoclasse, c'è qualcosa che non ci stai dicendo. –

+1

@ user2278797 Solo così sai: ho modificato la tua domanda per una migliore formattazione e cambiato i nomi delle classi (in quanto erano incoerenti tra il tuo codice): ho rimosso 's'-es dai loro nomi nelle linee in cui erano stati aggiunti 'animalList'. Erano: 'animalList.add (new Reptiles()); animalList.aggiungere (nuovi Uccelli()); animalList.add (new Anphibians()); 'E ora sono:' animalList.add (new Reptile()); animalList.add (new Bird()); animalList.add (new Anphibian()); '. Se li hai utilizzati in qualsiasi codice, assicurati di modificarli di conseguenza o di modificare di nuovo il codice della tua domanda. – acdcjunior

risposta

12

Non c'è davvero un buon modo per farlo dalla superclasse, poiché il comportamento di ciascuna sottoclasse sarà diverso.

Per assicurarsi che si stia effettivamente chiamando il metodo appropriato move, modificare Animal da una superclasse a un'interfaccia. Quindi, quando chiami il metodo move, sarai in grado di assicurarti di chiamare il metodo di spostamento appropriato per l'oggetto che desideri.

Se si desidera conservare i campi comuni, è possibile definire una classe astratta AnimalBase e richiedere a tutti gli animali di creare tale valore, ma ciascuna implementazione dovrà implementare l'interfaccia Animal.

Esempio:

public abstract class AnimalBase { 
    private String name; 
    private int age; 
    private boolean gender; 

    // getters and setters for the above are good to have here 
} 

public interface Animal { 
    public void move(); 
    public void eat(); 
    public void sleep(); 
} 

// The below won't compile because the contract for the interface changed. 
// You'll have to implement eat and sleep for each object. 

public class Reptiles extends AnimalBase implements Animal { 
    public void move() { 
     System.out.println("Slither!"); 
    } 
} 

public class Birds extends AnimalBase implements Animal { 
    public void move() { 
     System.out.println("Flap flap!"); 
    } 
} 

public class Amphibians extends AnimalBase implements Animal { 
    public void move() { 
     System.out.println("Some sort of moving sound..."); 
    } 
} 

// in some method, you'll be calling the below 

List<Animal> animalList = new ArrayList<>(); 

animalList.add(new Reptiles()); 
animalList.add(new Amphibians()); 
animalList.add(new Birds()); 

// call your method without fear of it being generic 

for(Animal a : animalList) { 
    a.move(); 
} 
+0

Ok, ma per quanto riguarda tutti i metodi e i comportamenti comuni condivisi tra le sottoclassi. Non sarebbe ridondante dichiarare gli stessi metodi e proprietà che fanno e descrivono le stesse cose in ogni sottoclasse separata? Ad esempio, ho alcuni nomi di proprietà comuni, genere, colore ecc. E poi alcuni metodi come mangiare e dormire. Grazie per le risposte veloci a proposito. – whiteElephant

+0

A questo punto, * potresti * avere un oggetto astratto chiamato "AnimalBase', che fornisce i campi di cui hai bisogno. Dovresti quindi estenderlo e implementare l'interfaccia 'Animal'. – Makoto

+0

Grazie Makoto, posso chiedere se esiste un modo più corretto per risolvere questo problema? per esempio. è meglio usare una classe astratta di base e implementare gli altri metodi o sarebbe meglio lasciare alcuni metodi vuoti e sovrascriverli per ogni sottoclasse? Cheers – whiteElephant

0

Nel tuo caso, quanto segue potrebbe funzionare, ma il tempo è la complessità O (n):

public void moveBird(){ 
    for(Animal aminal:animalList){ 
     if(animal instanceof Bird){ 
      aninmal.move(); 
     } 
    } 
} 
+0

Suppongo che ogni animale abbia un metodo move(). – BlackJoker

1

Non avete bisogno di fare qualsiasi casting. Il metodo override dovrebbe avere chiamato [semplice polimorfismo]

Animal aAnimal== this.animalList.get(animalIndex); 
aAnimal.move(); 

Sopra codice deve chiamare il metodo uccello se l'oggetto è di uccello, non è vero?

E il casting non è una soluzione, come deciderete quale oggetto trasmettere? Dovrai usare instanceOf.

+0

Grazie, potrebbe essere una possibile soluzione. Non sono sicuro di capire cosa intendi per E il casting non è una soluzione, come deciderai quale oggetto lanciare? Dovrai usare instanceOf ", L'utente farebbe clic su un oggetto, ad esempio un animale, e passerebbe il numero di indice di dove è collocato nell'arrayList. Cheers – whiteElephant

+0

Così facendo: animalList.add (nuovo Rettile()); animalList.add (nuovo uccello()); animalList.add (nuovo anfibio()); ora mentre si recuperano gli oggetti, è necessario tenere traccia di quale oggetto è in quale posizione eseguire il cast corretto o ho bisogno dell'istanza dell'operatore per verificare che altrimenti potresti finire col castare Anfibio in Bird. Hai capito? – Lokesh

+0

Ok, penso di sì - se lo facessi invece, – whiteElephant

-1
Bird getMyBird(Integer aniInteger) { 
     Bird b = new Bird(); 
     //Do somthig with bird object... 

     return b; 
     //get your modifeid bird object 
    } 

    Bird myBird = animalList.get(animalIndex); 

    myBird.move(); 
+2

Cosa stai facendo * * * con questo? Tutto quello che volevo fare era chiamare 'move' su qualsiasi tipo di 'Animal'. Perché sei così concentrato su 'Bird'? – Makoto

+0

Sì, non ci si concentra sull'uccello - lo usava solo come esempio. – whiteElephant

Problemi correlati