6

Attualmente sto leggendo Effective Java di Joshua Bloch e l'articolo 17 è "Progettare e documentare per ereditarietà o altrimenti vietarlo". L'autore suggerisce di vietare l'ereditarietà per impostazione predefinita.È possibile rimuovere la finale da una definizione di classe di interruzione della compatibilità?

È sicuro dichiarare le classi finali per impostazione predefinita e in una versione successiva rimuovere la parola chiave finale se è necessario estendere la classe? Romperà la compatibilità al contrario del codice che è stato compilato con una versione precedente?

Se è così sembra che sia una scommessa più sicura rendere definitiva tutte le classi e rimuoverla solo in una versione futura se c'è una domanda ben supportata.

+0

In qualche modo dipende da quante API viventi e respiranti possiedi. Se apporti modifiche e rilasci tutto il tempo, non è così male aspettare una settimana per avere la possibilità di ereditare. Se, d'altra parte, Java lo avesse fatto con le loro classi JDK di base per impostazione predefinita, avrebbe portato i programmatori in lacrime a dover aspettare 5 anni per la "correzione". –

+0

@Kirk Woll se occorrono 5 anni per passare dall'ultima alla non finale, quanto tempo ci vorrà per passare dalla non finale alla finale? – emory

risposta

10

Non rompe né la compatibilità binaria né la sorgente. Questo è uno dei motivi per cui è una buona idea rendere le lezioni finali; è sempre bene cambiare idea a riguardo.

The Java Language Specification, §13.4.2, ha quanto segue da dire sulla compatibilità binaria:

Modifica di una classe che è stata dichiarata final per non essere dichiarato final non rompere la compatibilità con i file binari pre-esistente.

Suppongo che ancora potrebbe comporre un esempio interpretata dove effettivamente potrebbe rompere un programma; come bytecode-generare una classe che eredita dalla classe presunta final e quindi caricare quella classe generata e fare affidamento su ottenere uno VerifyError.

2

Il mio pensiero su questo:

Rimozione del final su una classe non causano problemi immediati. Considerate questo:

C'era una classe finale chiamata AdamsFactory che cambiate in non finale. Tra due mesi, un nuovo programmatore chiamato Dilbert si unisce al tuo team.
Sottoclasse la tua classe da usato in ScottFactory, ma rompe il Principio di sostituibilità di Liskov.

Quindi ha la classe ComicStripPrinter che utilizza ScottFactory anziché AdamsFactory. Qualcosa è destinato a rompersi.

che ci riporta a quello che dice Joshua Block:

Se avete intenzione di successione: progettare con deliberazione, e documentarlo. Se non intendi l'ereditarietà, allora prevenilo.

Spero che quello che ho detto non sia stato un grande carico di merda.


EDIT:

andate alla preface of Java Langauge Specification, e la ricerca di Joshua Bloch :)

+1

La persona che ha progettato AdamsFactory non sapeva se renderlo definitivo/non finale, quindi PHB ha ordinato che fosse non-finale (per impostazione predefinita). Più tardi Dilbert rende un caso convincente per Adams Factory di essere definitivo, ma a questo punto ci sono circa un trilione di classi che estendono ad AdamsFactory qualche rompere il Principio di Liskov. Se Dilbert fa la modifica, tutte quelle classi sono rotte. Everone odia Dilbert. – emory

2

Se si sta progettando qualcosa di simile a Java Standard API, che milioni di programmatori utilizzeranno per molti anni, sì , pensa come Joshua Bloch. L'EVOLUZIONE IN AVANTI è fondamentale.

Il 99% dei programmi Java non lo sono. Sono sviluppati per uso interno, l'impatto della modifica dell'API è minuscolo, in genere tutti i codici sorgente sono disponibili per il refactoring.SEMPLICITÀ è la chiave per tali programmi. Se hai disegni complessi e fantasiosi, o passi tutto il tuo tempo a pensare alla finale o no, stai perdendo tempo.

Do la colpa a Joshua per non aver impostato i disclaimer per i suoi suggerimenti.

+2

Beh, YAGNI è tutto bello e dandy, ma cambiare il tuo modello di classe IDE Java per dichiarare tutte le classi come "final" è una cosa da fare una volta, e un design di classe sensato semplifica la manutenzione a lungo e medio termine (spesso ma non sempre , aiuta anche a breve termine), e navigare in una dichiarazione di classe e rimuovere 'final' è una cosa molto semplice da fare, se senti che dovresti averne bisogno. – gustafc

+0

mentre ci sei, rendi anche tutti i campi e i metodi finali. – irreputable