2015-05-22 9 views
11

Ho tre classi (il numero sarà probabilmente crescerà in futuro):lista Esclusione e la pratica Java

public inteface Base{ } 

public class Select implements Base{ } 

public class Ast implements Base{ } 

public class Gt implements Base{ } 

Ho anche bisogno di una classe List

BaseList extends ArrayList<Base>{ 
    public boolean add(Base b){ 
     throw new UnsupportedOperationException("You should use add%ConcereteBaseType% method instead"); 
    } 

    public boolean add(Select s){ } 

    public boolean add(Ast a){ } 

    public boolean add(Gt g){ } 
} 

Il motivo per cui l'ho fatto questo è il fatto che non voglio che qualcuno aggiunga elementi tramite un puntatore a Base. Nella mia situazione concreta questo sarebbe pericoloso.

Ma lo svantaggio è che verrà rilevato solo in fase di esecuzione.

Ho anche bisogno di scorrere l'elenco.

È una buona pratica fare queste cose?

+6

È più probabile che tutto questo sia un uso improprio dell'ereditarietà. Scommetto che qualunque cosa tu abbia in mente potrebbe essere realizzata con la composizione. – duffymo

+3

@duffymo Forse potresti dare un esempio per capire le cose di cui parli? –

+0

"Composizione" significa avere un 'ArrayList' come un campo piuttosto che estendere un' ArrayList'. (Vedere la risposta di my o memberssound ad esempio codice.) – aioobe

risposta

12

L'utilizzo di interface va bene. (Turning Base in una classe astratta non si compra nulla qui.)

Si dovrebbe favorire la composizione per l'eredità qui però, e implementare Iterable<Base> per essere in grado di utilizzarlo in avanzato per cicli ecc

class BaseList implements Iterable<Base> { 
    private List<Base> list = new ArrayList<>(); 

    public boolean add(Select s) { 
     return list.add(s); 
    } 

    public boolean add(Ast a) { 
     return list.add(a); 
    } 

    public boolean add(Gt gt) { 
     return list.add(gt); 
    } 

    @Override 
    public Iterator<Base> iterator() { 
     return Collections.unmodifiableList(list).iterator(); 
    } 
} 

È quindi possibile scorrere l'elenco come segue:

for (Base b : yourBaseList) { 
    ... 
} 
+0

utilizzando 'Collections.unmodifiableList (list) .iterator()' limita questo iteratore solo per scopi di spostamento. Perché dovrebbe essere necessario? Sembra una restrizione inutile per mitigare il potere ei vantaggi di 'Iterator'. – TheCurious

+0

@ dubey-theHarcortians, ammesso che sia una questione di design, e non è necessariamente la cosa giusta da fare. Aumenta comunque l'incapsulamento, quindi è la cosa difensiva da fare qui. Se OP sceglie di aggiungere un metodo 'remove' a' BaseList' per esempio, il 'unmodifiableList' dovrebbe essere definitivamente abbandonato. – aioobe

7

È possibile effettuare una classe abstract, in quanto questi non potrebbero mai essere istanziati, la vostra lista sarebbe al sicuro.

A modo mio: non capisco davvero perché ti piacerebbe lanciare un'eccezione per add(Base b) quando la base è un interface che di per sé non può mai essere un oggetto.

In caso contrario, utilizzare il modello delegato/wrapper, significa: Non estendere ArrayList, ma creare una classe contenente un ArrayList.

class BaseList { 
    private List<Base> list = new ArrayList<>(); 

    public boolean add(Select s) { 
     return list.add(s); 
    } 
    //etc 
} 
+0

re: primo punto, puoi ancora creare un'istanza di una sottoclasse, ma avere un riferimento di tipo 'Base'. Uso del delegato - continua, buon suggerimento. – vikingsteve

+2

Non vedo come rendere 'Base' una classe astratta farebbe alcuna differenza. Le stesse regole riguardanti l'istanziazione si applicano anche alle interfacce. – aioobe

+0

Ma non potrò iterare su BaseList con ciclo foreach quindi. Non è molto buono –

Problemi correlati