Chi estende le interfacce? E perché?


20

AFAIK, le mie classi extendsgenitore e le implementsinterfacce. Ma mi imbatto in una situazione, in cui non posso usare implements SomeInterface. È la dichiarazione di un tipo generico. Per esempio:

public interface CallsForGrow {...}

public class GrowingArrayList <T implements CallsForGrow>  // BAD, won't work!
                              extends ArrayList<T> 

Qui l'uso implementsè sintatticamente proibito. Ho pensato prima che l'uso dell'interfaccia all'interno di <> sia assolutamente proibito, ma no. È possibile, devo solo usare al extendsposto di implements. Di conseguenza, sto "estendendo" un'interfaccia. Questo altro esempio funziona:

public interface CallsForGrow {...}

public class GrowingArrayList <T extends CallsForGrow>  // this works!
                              extends ArrayList<T> 

A me sembra un'incoerenza sintattica. Ma forse non capisco alcune finezze di Java 6? Ci sono altri posti in cui dovrei estendere le interfacce? L'interfaccia, che intendo estendere, dovrebbe avere alcune funzionalità speciali?

Risposte:


25

Nel caso di variabili di tipo generico, al compilatore non importa se si Ttratta di una classe, un'interfaccia, un enum o un'annotazione. Tutto ciò che importa è che è un tipo con un determinato set di sottotipi e super-tipi.

E non c'è motivo di complicare la sintassi solo perché in un altro posto (in cui si implementa effettivamente un'interfaccia) è rilevante la distinzione tra classi e interfacce (ad esempio se si è implementun'interfaccia, è necessario implementare tutti i metodi che definisce, ma tu non è necessario, se sei extenduna classe (non astratta)).

Supponendo per un momento che dovresti scrivere implementsqui, allora avresti anche bisogno di una sintassi separata per enumvalori (invece di scrivere semplicemente <E extends Enum<E>>) e annotazioni (che puoi facilmente dichiarare usando <A extends Annotation>).

L'unico posto in cui è necessario scrivere implementsè nel punto in cui si implementa effettivamente l'interfaccia. A quel punto (e solo a quel punto) la differenza è importante, perché è necessario implementare i metodi definiti nell'interfaccia. Per tutti gli altri, non importa se qualsiasi dato Aè una classe base o un'interfaccia implementata di B: è un super-tipo e questo è tutto ciò che conta.

Nota anche che c'è un altro posto in cui usi le extendsinterfacce:

interface A {
}

interface B extends A {
}

A questo punto implementssarebbe sbagliato, perché B non implementa A .


Se useremo i vostri logica, dovremmo usare 'si estende SomeInterface' sempre , non solo in farmaci generici.
Gangnus,

2
@Gangnus: no, perché per l' implementatore c'è una differenza concreta tra extendse implements, è solo quando si guarda al problema da una prospettiva di puro sistema-tipo, che non c'è differenza.
Joachim Sauer,

1
Scusa, non capisco il tuo pensiero. --1. Perché dovremmo usare "una prospettiva di sistema di tipo puro" in un caso e non nell'altro? --2. Perché le richieste sintattiche cambiano in questi diversi luoghi? Potresti spiegarlo, per favore. Nella risposta, se possibile.
Gangnus,

1
@Gangnus: chi dice che Tsia una classe? Tpotrebbe fare riferimento a un tipo di interfaccia o un enumtipo.
Joachim Sauer,

1
proveniente da C #, tutta questa discussione è ridicola. denotiamo i supertipi di un tipo con :. e sotto le coperte, un'interfaccia è ed è sempre stata una classe astratta con il vincolo di contenere solo abstractmembri virtual ( ) non implementati , in modo da consentire l'ereditarietà multipla. non c'è letteralmente alcuna differenza tra implementse extends. entrambi potrebbero essere sostituiti con la stessa parola ( extends) o con un simbolo arbitrario ( :) e nulla andrebbe perso.
Sara

5

Quando Java 5, e in particolare i generici, furono inizialmente resi disponibili agli sviluppatori che avevano registrato un interesse, la sintassi era piuttosto diversa. Invece di Set<? extends Foo>e Set<? super Bar>aveva Set<+Foo>e Set<-Foo>. Tuttavia, il feedback è stato che non era chiaro se +significasse più specifico o più ampio (più classi) . Sun ha risposto a quel feedback modificando la sintassi, ma con il vincolo di non introdurre nuove parole chiave, il che sarebbe stato un problema per la retrocompatibilità.

Il risultato è che nessuno dei due è del tutto naturale. Come si osserva, extendsè sovraccarico di parlare di interfacce di "estensione" delle classi, che non è il linguaggio usato in altri contesti; ed superè sovraccarico di significare "è una superclasse di", che è la direzione opposta della relazione precedentemente espressa dalla parola chiave, vale a dire riferendosi a una superclasse.

Tuttavia, i fondamenti di ciò che un'interfaccia è non sono interessati da questo cambiamento e non introducono interfacce speciali che vengono estese in un modo nuovo.


+1. Vedo e sono d'accordo. Ma Joachim Sauer ha trovato il mio erroneo pensiero che T sia necessariamente una classe. Quindi, la risposta è sua. La tua comprensione è di uno (o 2) piano più alto :-). Il mio problema era più primitivo. Grazie comunque per il mio sviluppo.
Gangnus,

2

Ci sono degli svantaggi sia nel consentire che nel proibire tale sintassi, e quelli nel consentire sono di gran lunga maggiori.

Pensaci.

La separazione dell'interfaccia e l'implementazione è uno dei linguaggi di programmazione fondamentali. Per questo motivo, la sintassi che consente di scrivere "interfaccia implementa qualcosa" sarebbe tanto grave quanto quella che usa il segno più per indicare la moltiplicazione degli operandi.


Ok. Quindi, davvero non capisco qualcosa. L'ho considerato molto probabile. Ma non hai affatto spiegato il problema, scusa. T è una rappresentazione di una classe. Perché in un posto uso T si estende e in un altro attrezzo T?
Gangnus,

@Gangnus nell'esempio che hai fornito T si riferisce al parametro type che non è necessariamente una classe - vedi cosa Joachim ti ha già detto . Consentire strumenti per questo porterebbe allo stesso pasticcio che ho menzionato
moscerino del

Sì, ho già visto il suo commento. Verrà contrassegnato come risposta una volta inserito nella risposta. Fino a quando entrambi avete i miei ringraziamenti e +1.
Gangnus,

-1

È necessario comprendere la programmazione basata sull'interfaccia come passaggio successivo mentre si comprende un'interfaccia. Indica qual è l'uso effettivo dell'interfaccia. Quale ruolo gioca in un programma Java (o in qualsiasi altra lingua).


2
In che modo la tua risposta affronta le preoccupazioni del PO? Si prega di modificare la risposta ad essere più chiaro.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.