2012-05-04 19 views
5

Questa sembra una domanda java di base.Informazioni sul sottotipo sottotabella Java

Ho un'interfaccia, Pipeline, che ha un metodo execute(Stage).

Quindi creo un'interfaccia secondaria da estendere da Pipeline, ad esempio BookPipeline, il metodo è execute(BookStage).

BookStage si estende da Stage.

Sembra che questo tipo di definizione non possa passare a java compile.

Qualche suggerimento su questo?

+1

Qual è il messaggio di errore del compilatore? Qual è il tuo codice? –

risposta

6

Si consiglia di considerare l'utilizzo di generici.

public interface Pipeline<T extends Stage> { 
    public void execute(T stage); 
} 

public interface BookPipeline extends Pipeline<BookStage> { 
    @Override 
    public void execute(BookStage stage); 
} 
+4

Non è la dichiarazione di 'execute' in' BookPipline' in ridondante? –

+0

@KirkWoll Sì, è lì per l'esempio – Jeffrey

+0

Gotcha, non ho bisogno di sovrascriverlo. Grazie mille! – BlueDolphin

4

Oltre a ciò che @Jeffrey ha scritto come una possibile soluzione, è importante capire perché non è possibile farlo.

Supponiamo tu avessi un'interfaccia Pipeline con un metodo execute(Stage), e un'interfaccia che si estende BookPipeline con execute(BookStage).

Si supponga inoltre di avere una classe Conc che implementa BookPipeline.

Si consideri il seguente

Pipeline p = new Conc(); 
p.execute(new Stage()); 

che cosa accadrà? Non sarà sicuro!
Java vuole evitarlo e quindi prevenire queste situazioni dal primo posto.

La regola è un'estensione di classe/interfaccia può aggiungere un comportamento, ma non ridurlo.

+0

Ottimo punto, grazie! – BlueDolphin

0

Giusto per elaborare la risposta s' @amit, il frammento di codice è pericoloso come il metodo Conc.execute prende un BookStage come parametro e questo sarebbe cercare di spremere un Stage al posto di quella (e, naturalmente, non tutti Stage s sono BookStage s).

Tuttavia, immaginare abbiamo voluto andare nella direzione opposta, cioè, fanno il tipo di parametro del BookePipeline.execute un super- tipo di Stage, come ad esempio Object.

Quindi, solo per chiarire, avremmo:

interface Pipeline 
{ 
    void execute(Stage s); 
} 

interface BookPipeline extends Pipeline 
{ 
    @Override 
    void execute(Object s); 
} 

E dove Conc attrezzi BookPipeline:

Pipeline p = new Conc(); 
p.execute(new Stage()); 

Questo sarebbe, in teoria, essere al sicuro perché Liskov sostituibilità non è stata violata - abbiamo potrebbe tranquillamente passare un Stage in qualsiasi implementazione che abbia un parametro Stage o superiore. Questo è noto come controvarianza. Java non supporta i tipi di argomenti controvarianti, tuttavia ci sono languages che fanno.

tua domanda iniziale si riferisce a covariante tipi di argomenti che è pericoloso per i motivi specificati (tuttavia stranamente, un linguaggio chiamato Eiffel permette questo).

Java supporta tuttavia covariant restituisce tipi. Immaginate Pipeline aveva un

Stage getAStage(); 

sarebbe perfettamente legale per BookPipeline per ignorare questo metodo in questo modo:

@Override 
BookStage getAStage(); 

Poi immaginate che abbiamo avuto:

public void someMethodSomewhere(Pipeline p) 
{ 
    Stage s = p.getAStage(); 
    //do some dance on Stage 
} 

Supponendo che abbiamo avuto qualche classe Donc che ha implementato Pipeline e ha annullato getAStage() esattamente come è definito in Pipeline (così ancora il ritorno Stage), entrambi di queste chiamate sono OK:

someMethodSomewhere(new Conc()); 
someMethodSomewhere(new Donc()); 

perché possiamo sempre mettere un qualcosa di Stage o meno (per esempio BookStage) in una variabile di tipo Stage.

Quindi, per riformulare la regola di mettere in relazione in particolare al metodo di primaria importanza, una classe/interfaccia che si estende che sostituisce i metodi, non può che rendere tali metodi più generali in quello che accettano e più specifiche in quello che ritornano. (anche se nel caso di Java, tipi restituiti solo più specifiche sono ammessi.)

Basta ricordare, PECS - Produttore Estende, Super consumatori (Joshua Bloch, Effective Java)