2010-10-16 22 views
6

Come esempio pratico della questione generale in materia, vorrei implementare il metodo containsAll nell'interfaccia Set conattuazione Interfaccia con metodo argomento superclassi

public boolean containsAll(Iterable<?> c) { /* ... */ } 

immagino questo dovrebbe essere consentito, poiché Collection è Iterable che significa che un tale containsAll coprirebbe i requisiti dell'interfaccia. Allo stesso modo, più generalmente la possibilità di implementare interfacce con superclassi di argomenti sembra che dovrebbe funzionare.

Tuttavia, Eclipse non dice in alcun modo (non ho provato solo javac straight-up) - qualcuno può spiegarne il motivo? Sono sicuro che ci sia qualcosa nelle specifiche che lo rende così com'è, ma mi piacerebbe capire anche la motivazione del requisito. O mi manca qualcosa come Iterable<?> non essendo una superclasse di Collection<?>?

Come una domanda a parte: dato che sto dichiarando due metodi, il metodo con la firma Iterable sarà sempre preferito per le chiamate con un argomento Collection?

Eclipse Errore:

Se rimuovo il metodo con la firma Collection, semplicemente lasciando il Iterable uno (vedere dopo errore), ottengo il seguente:

The type BitPowerSet must implement the inherited abstract method Set<Long>.containsAll(Collection<?>)

L'esatta essere implementazione :

@Override public boolean containsAll(Collection<?> c) { 
    for (Object o : c) if (!contains(o)) return false; 
    return true; 
} 
public boolean containsAll(Iterable<?> c) { 
    for (Object o : c) if (!contains(o)) return false; 
    return true; 
} 
+0

Potresti pubblicare un errore che Eclipse ti sta dando? Lavora per me in IDEA. –

+0

@Nikita: modificato in. Soooo ... potrebbe essere solo una cosa di Eclipse? – Carl

+0

Questo è un incubo terminologico. Fuggo da queste sfide. – skaffman

risposta

2

La mia ipotesi sul motivo per cui Java ha questa limitazione è, supponiamo di avere:

class A { 
    void foo(String s) { ... } 
} 

class B extends A { 
    // Note generalized type 
    @Override void foo(Object s) { ... } 
} 

Ora, se avete class C extends B e vuole ignorare foo, non è chiaro quale argomento che dovrebbe assumere.

diciamo per esempio C esteso A direttamente in un primo momento, ignorando void foo(String s), e poi è stato cambiato per estendere B. In questo caso di C esistente forzatura dei foo diventerebbe nullo a causa B di foo dovrebbe essere in grado di gestire tutte le Object s, non solo String s.

+0

ah, questa sembra essere una spiegazione ragionevole - l'ampliamento dell'interfaccia richiederebbe alle sottoclassi di mantenere l'interfaccia ampliata. Tuttavia, sembra che dovrebbe essere consentito - in genere, le sottoclassi non sono autorizzate a restringere le interfacce. – Carl

+0

Probabilmente rende anche più chiaro il disegno della tabella virtuale per affermare che tutti i metodi in esso contenuti hanno la firma esatta. O forse hanno semplicemente pensato che avrebbero potuto farlo funzionare se lo avessero fatto abbastanza, ma non hanno visto un bisogno irresistibile e lo hanno lasciato fuori. – oksayt

+0

Mi manca qualcosa - questo esempio dovrebbe funzionare? Nell'annotazione @ Override viene visualizzato il messaggio "Il metodo non sovrascrive il metodo dalla sua superclasse". – Amalgovinus

5

Poiché l'interfaccia che si sta implementando dichiara (in astratto) metodo containsAll(Collection<?>), è necessario implementarlo con questa firma esatta. Java non consente di implementare/sovrascrivere un metodo con un tipo di parametro più ampio rispetto all'originale. Questo è il motivo per cui viene visualizzato l'errore che viene visualizzato quando si commenta il metodo con la firma Collection.

Non si visualizza l'altro errore che si afferma di ottenere quando il metodo non è commentato, ma suppongo che potrebbe dover fare qualcosa con un sovraccarico di metodo ambiguo.

+0

Nessun errore quando il metodo non è commentato. Solo quando quello con la firma 'Collection' è. – Carl

+0

Inoltre, qualche idea sul perché questo è il caso? È sulla falsariga della risposta di @ oksayt? – Carl

+0

@Carl, vuoi dire perché Java è progettato così? Potrebbe essere. –

0

I tipi di argomento fanno parte della firma del metodo, quindi jvm richiede un metodo con la stessa firma esatta per trovare le sostituzioni. A containsAll (Iterable) avrà una firma diversa da containsAll (Collection).

Se ricordo bene, il compilatore deve usare qualche soluzione per far funzionare i generici nonostante questa limitazione.

Alla seconda domanda, il compilatore preferirebbe l'argomento Raccolta poiché si tratta di un sottotipo di Iterable, ciò rende il metodo di raccolta più specifico di quello Iterable.

Problemi correlati