2016-06-18 51 views
11

So che cosa significa implementare un'interfaccia (tecnicamente), ma non sono sicuro di capire cosa comprende il "contratto":Una classe deve aderire al contratto documentato di un'interfaccia per implementare tale interfaccia

Diciamo che faccio una classe MyList che implementa java.util.List (ovvero, implemento tutti i metodi con il codice che compila), è MyList a List quindi? O devo leggere tutti i commenti sui metodi che ho scavalcato e assicurarmi che la mia implementazione soddisfi queste "aspettative" sul comportamento?

+0

MyList è una lista? Sì – Enzokie

+0

@Enzokie Quindi devo implementare 'add' per non fare nulla e' get' per restituire sempre null, lo chiameresti comunque un elenco? –

+0

Finché si implementa l'Elenco, viene comunque chiamato un elenco. Alla fine della giornata è la tua decisione se metti qualcosa su quei metodi implementati o lanci qualche eccezione non supportata, il fatto rimane che è ancora chiamato una lista. – Enzokie

risposta

12

Tecnicamente, sì, MyList è un List se implementa tutti i metodi dell'interfaccia List. Ma il compilatore non è un mago. Non può controllare che i tuoi metodi facciano ciò che dovrebbero fare. E, naturalmente, ogni metodo dovrebbe fare ciò che la sua documentazione dice che fa.

se ricevo un List, e questo List è un'istanza di MyList, e chiamo list.add("foo"), mi aspetto "pippo" da aggiungere alla fine della lista. Non essere rimosso, o aggiunto due volte o qualunque altro comportamento. Quindi, ovviamente, se la tua classe implementa List, i suoi metodi dovrebbero essere conformi al contratto definito nella sua documentazione API.

Immagina di vendere auto. Vado al tuo negozio e compro un'auto. Per me, è un'auto perché assomiglia a tutte le altre macchine: ha ruote, pedali, finestre, ecc. Ma se premo l'acceleratore, frena, e quando accendo le luci, suona, e quando apro Windows, accelera e uccide un povero ragazzo sulla strada, non sarò affatto felice e sarai nei guai perché l'auto che mi hai venduto non si comporta in modo corretto.

+0

Haha ottimo esempio +1 – rpax

+0

Quindi non esiste un modo formale per dire se la mia implementazione è "giusta" o "sbagliata", sembra piuttosto vaga, si tratta di aspettative (informali). Sarebbe bello se l'interfaccia/classe astratta fosse accompagnata da un test unitario che decida se la classe di implementazione soddisfa tutte le aspettative. Attualmente la documentazione dell'API potrebbe cambiare, rendendo improvvisamente invalida la mia implementazione (a mia insaputa). –

+0

Il JDK non fornisce questo test unitario. Spetta a te implementarlo. Ma il contratto non cambierà mai: ciò spezzerebbe tutto il codice Java esistente. L'implementazione di una raccolta standard non è affatto un'attività comune. Il JDK e le librerie comuni come Guava forniscono tutto il necessario per il 99,999% dei casi d'uso. Non riesco a ricordare di aver implementato una raccolta standard una volta nei miei 20 anni di programmazione Java. –

2

In Java, la differenza tra una classe e un'interfaccia è che una classe ha implementazioni di metodo. Un'interfaccia no. Quindi un'interfaccia potrebbe avere un metodo add(), ma non dirà nulla su come funziona l'aggiunta. Una classe dovrebbe definire come funziona l'aggiunta.

Si implementa un'interfaccia nel momento in cui si inserisce implements InterfaceName nella definizione della classe. Devi quindi definire tutti i metodi dell'interfaccia, altrimenti la tua app non verrà compilata. Allora sì, sarebbe corretto dire che MyClass è un MyInterface - potresti persino passare all'interfaccia MyInterface = new MyClass();

E sì, dovresti leggere tutti i commenti e assicurarti che la tua classe implementa l'interfaccia nel modo previsto. Altrimenti finirai con qualcosa che compila ma potrebbe non funzionare correttamente.

+0

no, java.util.List non è una classe –

+0

Risolto il problema prima ancora di aver postato questo :) –

+1

Uh..java 8+ consente l'implementazione sull'interfaccia. Limitato, ma è possibile. – rpax

1

L'interfaccia è un minimo necessario per il contratto: come dici tu, se non viene compilato, non puoi aver soddisfatto il contratto! Ma la lingua potrebbe non essere in grado di definire e limitare i requisiti dell'interfaccia, quindi dovresti tenere conto anche di quelle aspettative.

Un semplice esempio è l'interfaccia ICloneable. Se tutto ciò che fai è implementare

public MyObject clone() { 
    return (MyObject)super.clone(); 
} // clone() 

allora hai adempiuto il contratto di lingua, e forse la classe contratto di troppo. Ma se la tua classe contiene uno , allora sorprenderesti i tuoi utenti: "Questo non ha fatto il clone() giusto!"

Il contratto include anche le aspettative degli utenti. Spezzali e, sebbene un avvocato linguistico possa dire che la tua classe è-a List, gli altri non saranno d'accordo ..

+0

Qual è l'interfaccia 'ICloneable' di cui si sta parlando? [java.lang.Cloneable] (https://docs.oracle.com/javase/8/docs/api/java/lang/Cloneable.html) è un'interfaccia marcatore e non ti obbliga nemmeno a sovrascrivere il 'clone () '. Ma hai ragione, le interfacce marker ([Serializable] (https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html) sarebbero un altro esempio popolare) esistono solo come una sorta di promessa di adempiere al contratto - è banale fare compilare un'implementazione, ma senza anche rispettare il contratto, è inutile. – Hulk

0

è MyList a List?

Al fine di rispondere a questa domanda è necessario prima capire che cosa fare o interfacce cosa stanno scritto per ...

Non dimenticate interfacce in grado di offrire un distacco importante tra ciò che una classe può fare e come lo fanno ... quindi tecnicamente l'attuazione di un interfaccia non è di chiedere se un oggetto è qualcosa ma più di chiedere come un oggetto può fare qualcosa

quindi quando dici List myContainer = new ArrayList(); si sta definendo un oggetto che può fare tutte le cose che un elenco può fare ... aggiungere, rimuovere, ottiene etc etc

si può dire che esso Una lista, direi che può fare quello che un elenco può fare ..

Problemi correlati