2015-02-27 16 views
13

Angelica Langer dice nella sua FAQ sui farmaci generici (vedi Technicalities.FAQ822):override un metodo generico per un generico in Java

Se i metodi hanno parametri di tipo con diversi limiti, allora non ignorare, perché i metodi hanno firme che non sono equivalenti a override. Ricorda, i limiti del parametro tipo fanno parte di la firma di un metodo generico.

Esempio (di metodi sottotipo generici sovraccarico Supertype generico metodi; non raccomandati):

class Super { 
    public <T> void set(T arg) { ... } 
    public <T> T get() { ... } 
} 
class Sub extends Super { 
    public <S extends Number > void set(S arg) { ... } // overloads 
    public <S extends Number > S get() { ... }   // overloads 
} 

non capisco il motivo per cui il metodo get è sovraccarico in classe Sub. Per quello che so dovrebbe essere un errore in fase di compilazione perché get ha la stessa firma sia in Sub che in Super (il tipo di reso non fa parte di esso).

Cosa mi confondere ancora di più è che l'IDE sto usando per testare il codice (IntelliJ IDEA 14.0.3) evidenzia get in Sub come un errore di compilazione con il messaggio successivo:

'get () 'in' Sub 'si scontra con' get() 'in' Super '; entrambi i metodi hanno la stessa cancellazione, ma nessuno dei due ha la precedenza sull'altro.

Ma quando eseguo il programma, esso viene compilato ed eseguito senza problemi. Suppongo che ci sia una specie di bug in IntelliJ quando analizza il codice, e cosa è corretto è ciò che Angelica dice nelle sue FAQ. Ma non riesco a capire il punto.

+2

In Eclipse è possibile impostare il compilatore incorporato per essere più rigoroso e considerare alcune condizioni come errori (come l'assegnazione a self o l'accesso a un metodo statico attraverso un'istanza). Suppongo che lo stesso si possa fare anche in IDEA. – biziclop

+0

Qual è il problema che si verifica è che il parametro di tipo del metodo sottoposto a override non ha gli stessi limiti come il parametro di tipo del metodo dalla super classe. –

+6

Come detto nel post che citi, _ i limiti del parametro di tipo fanno parte della firma di un metodo generico_. Quindi ' T get()' e ' S get()' ha diverse firme. Il clash del nome è ancora brutto, quindi è così che il poster dice che non è raccomandato_ –

risposta

0

Penso che la cancellazione di public <S extends Number> S get() non sia la stessa o covariante di public <T> T get().

Questo viene compilato ed eseguito:

class B { 
    public <T> T get() { 
     return null; 
    } 

} 

class A extends B { 
    @Override 
    public <S> S get() { 
     return null; 
    } 

Questo non significa:

class B { 
     public <T> T get() { 
      return null; 
     } 

    } 

    class A extends B { 
     @Override 
     public <S extends Number> S get() { 
      return null; 
     } 
+0

Questo è corretto. Il primo codice viene compilato ed eseguito, e il secondo no, perché stai usando l'annotazione '@ Override' in' get'. So per le domande frequenti di Angelika Langer che è sovraccarico, non sovrascritto. Quello che non capisco è _why_. – Bleyder

+0

@Bleyder Poiché 'S' e' T' sono parametri di input. – biziclop

+0

@biziclop 'S' e' T' sono parametri di input in _both_ esempi. Tuttavia, nel secondo caso si tratta di un errore in fase di compilazione poiché 'B' non è un metodo di override' get' ... è sovraccarico! Perché è così? Come può 'B' nel secondo esempio sovraccaricare e non sovrascrivere? – Bleyder

0

Da quello che ho capito, perché si sta sovraccaricando invece di prevalente è perché il compilatore non lo vede come esclusione -equivalente. Più avanti nelle FAQ di Angelika Langer, vedi come discute sul motivo per cui ignorare un metodo non è come previsto.

http://www.angelikalanger.com/GenericsFAQ/FAQSections/ProgrammingIdioms.html#FAQ051

Riassumendo, i metodi hanno lo stesso hanno gli stessi nomi e parametri ma sulla base del sottotipo generico sono definiti come diversi. Anche con l'annotazione di sovrascrittura, il compilatore lo vede come un metodo sovraccarico. Nell'uso di generici, c'è un livello aggiunto a un metodo, in cui il tipo generico si applica come parte del metodo che può definirlo univocamente.

1

In base a JLS, la firma del metodo non include il tipo restituito ma solo il nome del metodo e il tipo dei relativi parametri. Ciò significa che durante la compilazione di Super e Sub, un errore di compilazione deve essere restituito poiché Sub.get() ha la stessa cancellazione di Super.get(), ma né sovrascrive né sovraccarico Super.get(). Non può eseguire l'override perché il tipo limitato X estende Number non è un sottotipo del tipo X e non può essere sovraccaricato perché il tipo restituito non fa parte di una firma del metodo. Sovraccarico di sottosistemi Super.set in questo caso.

Sul motivo per cui è possibile compilare ed eseguirlo. Se stai usando Java 6, c'è un noto bug in Java 6 che compilerebbe Super e Sub. In Java 7 questo è fisso e non sarebbe permesso.

Problemi correlati