OOP: quali sono alcune delle situazioni in cui il design basato sulla classe è migliore di quello basato sull'interfaccia?

9

Stavo leggendo il sito web di JDOM .

Why is the JDOM API defined in terms of concrete classes rather than interfaces?

Jason Hunter summarizes the arguments against an interface-based API for JDOM:

With interfaces everything becomes a factory, elements have to be 'imported' into new documents instead of just added, features like long-term serialization cannot be guaranteed, and the list goes on.

We started with interfaces actually. During our pre-release review to some peers we received the feedback we should try concrete classes. We did, and the design was much better for it.

Sono un designer principiante. Tutti i consigli di cui ho sentito parlare finora sono sconsigliamo di utilizzare la progettazione con lezioni concrete.

Le classi concrete possono essere appropriate in determinati luoghi. Ci sono problemi di classe comuni per i quali l'uso di classi concrete nel design è ok?

    
posta Vinoth Kumar C M 09.05.2012 - 12:13
fonte

5 risposte

5
  • L'ereditarietà crea dipendenze all'implementazione , il che potrebbe essere un grosso problema per quanto riguarda la gestibilità. Il corollario di questo è che puoi tranquillamente usare l'ereditarietà e le classi concrete quando si tratta di oggetto di trasferimento dati , che per definizione non contiene quasi nessuna implementazione. È inoltre possibile utilizzare l'ereditarietà delle classi concrete quando si desidera questa dipendenza. Potresti voler utilizzare una classe astratta contenente i metodi comuni (di solito le funzioni di utilità) nella parte superiore della gerarchia in questa situazione.
  • Quando si utilizza una gerarchia di classe concreta, non dimenticare di applicare il principio di sostituzione di Liskov .
  • Non c'è alcun problema con l'utilizzo di classi concrete per i client (cioè classi che utilizzano, non classi che vengono utilizzate).
  • IMHO puoi usare lezioni concrete finché non ci sono cose da cambiare. Il Principio Aperto / Chiuso ti direbbe di usare le interfacce per evitare l'accoppiamento, ma per quanto riguarda Lei non ne ha bisogno ne ha il principio potresti prendere in considerazione l'utilizzo di lezioni concrete fino al momento in cui devi modificare qualcosa nell'implementazione. Il problema è che dovresti cambiare ogni client delle tue classi la prima volta che qualcosa cambia da qualche parte. Mentre hai solo uno strumento possibile per fare qualcosa, puoi usare le classi concrete IMO.

[EDIT] Il sito web di JDOM prende come esempio un file java.io.File, ma si tratta sicuramente di un progetto basato sull'interfaccia in quanto si può manipolare un'istanza java.io.File come se fosse solo una Serializable. In questa situazione solo i "creatori" conoscono la classe concreta

    
risposta data 09.05.2012 - 13:13
fonte
2

Dal sito JDOM:

Jason (Hunter) founded the JDOM project in early 2000 along with Brett McLaughlin

Cioè, all'incirca quando Java 1.3 è stato introdotto. Non c'era nulla in termini di maturità quando si trattava dello sviluppo di Java: gli sviluppatori più esperti avevano solo 4 anni usando Java nella migliore delle ipotesi. Non c'erano contenitori IoC largamente usati, nessun Hibernate. Apache Struts stava per iniziare.

Il che significa che Jason e Brett si sbagliavano. Un sacco di gente non ha ancora "capito". Se avessero sfondi in C ++, beh, non avevi bisogno di interfacce in C ++ (beh, erano in C ++, ma non ne avevi davvero bisogno, giusto?), Perché diamine usarle in Java? Bene, ci sono molte buone ragioni, a cui altri possono indirizzarti.

Erano decisamente sbagliati su

anything that can be done with interfaces can be done with subclassing

Java non consente l'ereditarietà multipla delle classi, ma consente l'implementazione di più interfacce. Questo può fare davvero la differenza.

    
risposta data 09.05.2012 - 18:08
fonte
2

Ricorda, innanzitutto, che nello sviluppo di software ci sono diversi modi per risolvere un problema, e se alcuni sviluppatori usano una tecnica diversa dalla tua, ciò non significa che sia sbagliato.

Uno di questi casi è "interfaces" contro (base) "classi". Ci sono situazioni in cui lo stesso obiettivo può essere raggiunto con entrambe le tecniche.

Per rendere le cose, più complicate, ci sono diversi usi delle interfacce,  solo per citare:

  • uno è progettare un "contratto" o "specifica" senza "implementazione"
  • altro per aggiungere functuonality a una classe esistente o una gerarchia di classi
  • complementare al precedente, per consentire l'accesso condiviso tra diversi oggetti, tecnologie, esempio: Enterprise Beans, CORBA, COM, WebServices
  • per emulare l'ereditarietà multipla

La tua domanda si applica al primo punto.

Quando vuoi sviluppare una gerarchia di classi, non solo una singola classe, e diverse classi hanno lo scopo di condividere alcune caratteristiche specifiche, potresti voler iniziare con una classe base, anche se può essere fatta con un'interfaccia.

E lascia le interfacce per gli altri scenari.

Un buon esempio sono le librerie di widget (controlli).

Suggerisco di dare un'occhiata ad altri linguaggi di programmazione come usano le interfacce e l'ampli; classi come: PHP, Delphi (Object Pascal), C #.

Saluti.

    
risposta data 10.05.2012 - 04:39
fonte
0

In genere si desidera un'interfaccia per tutto ciò che viene passato come parametro o restituito, essenzialmente in modo da poter separare la classe dalle sue dipendenze.

Quindi, se stiamo cercando una classe che non passiamo mai, normalmente vengono in mente le eccezioni. Non sono uno sviluppatore Java, ma sicuramente in altre lingue simili non penso di aver visto le interfacce definite per le eccezioni.

    
risposta data 09.05.2012 - 12:22
fonte
0

Le regole di progettazione dell'API sono davvero una cosa specifica. Non sono sicuro che dovresti concludere qualcosa da queste FAQ in termini di come dovresti progettare il tuo codice giornaliero.

Per il tuo codice normale, è ancora vero che utilizzerai l'ereditarietà di una classe astratta o di un'interfaccia molto più spesso di IMO per l'ereditarietà della vaniglia.

Per ottenere una buona comprensione di tale regola, devi posizionarti non dal punto di vista di una classe derivata rispetto alla sua superclasse, ma dal punto di vista di un oggetto che ha una dipendenza da un altro oggetto. È quasi sempre meglio dipendere da un'astrazione piuttosto che da un'implementazione concreta perché consente di accettare un'intera serie di classi diverse come dipendenze, facendo affidamento sul proprio contratto e non sui dettagli di implementazione.

Il primo utilizzo di questo è spesso in unit test: se vuoi davvero unit testare la tua classe in completo isolamento, lo fai contro false implementazioni delle tue dipendenze che sono diverse dalle reali implementazioni che verrà utilizzato in produzione.

    
risposta data 10.05.2012 - 14:43
fonte

Leggi altre domande sui tag