Perché usare 'final' su una classe è davvero così brutto?

32

Sto rifattorizzando un sito web legacy OOP di PHP.

Sono così tentato di iniziare a utilizzare "final" sulle classi su " make it explicit that the class is currently not extended by anything ". Questo potrebbe risparmiare un sacco di tempo se vengo in una classe e mi chiedo se posso rinominare / eliminare / modificare una proprietà o un metodo protected . Se io davvero voglio estendere una classe, posso semplicemente rimuovere la parola chiave finale per sbloccarla per estenderla.

I.e Se vengo in una classe che non ha classi di bambini, posso registrare quella conoscenza segnando una finale alla classe. La prossima volta che ci andrò non dovrò cercare di nuovo la base del codice per vedere se ha figli. Così risparmiando tempo durante i refactoring.

Sembra un'idea ragionevole per risparmiare tempo .... ma ho letto spesso che le lezioni dovrebbero essere fatte solo in occasioni rare / speciali.

Forse rovina la creazione di oggetti Mock o ha altri effetti collaterali a cui non sto pensando.

Cosa mi manca?

    
posta JW01 02.07.2011 - 14:10
fonte

6 risposte

53

I have often read that classes should only be made 'final' on rare/special occasions.

Chi ha scritto è sbagliato Usa final liberamente, non c'è niente di sbagliato in questo. Documenta che una classe non è stata progettata pensando all'ereditarietà, e di solito è vera per tutte le classi per impostazione predefinita: progettare una classe che può essere significativamente ereditata da richiede più della semplice rimozione di un identificatore final ; ci vuole molta cura.

Quindi usare final di default non è affatto male. In effetti, molte persone propongono che questo dovrebbe essere l'impostazione predefinita, ad es. Jon Skeet .

Maybe it screws up Mock object creation …

Questo è davvero un avvertimento, ma puoi sempre ricorrere alle interfacce se hai bisogno di prendere in giro le tue lezioni. Questo è certamente superiore a rendere tutte le classi aperte all'eredità solo allo scopo di prendere in giro.

    
risposta data 14.07.2011 - 09:00
fonte
8

Se vuoi lasciare una nota a te stesso che una classe non ha sottoclassi, allora fallo con tutti i mezzi e usa un commento, questo è quello che servono. La parola chiave "finale" non è un commento e usare parole chiave linguistiche solo per segnalarti qualcosa (e solo tu mai sapresti cosa significa) è una cattiva idea.

    
risposta data 02.07.2011 - 15:06
fonte
5

C'è un bell'articolo su "Quando dichiarare le classi finali" . Alcune citazioni da esso:

TL;DR: Make your classes always final, if they implement an interface, and no other public methods are defined

Why do I have to use final?

  1. Preventing massive inheritance chain of doom
  2. Encouraging composition
  3. Force the developer to think about user public API
  4. Force the developer to shrink an object's public API
  5. A final class can always be made extensible
  6. extends breaks encapsulation
  7. You don't need that flexibility
  8. You are free to change the code

When to avoid final:

Final classes only work effectively under following assumptions:

  1. There is an abstraction (interface) that the final class implements
  2. All of the public API of the final class is part of that interface

If one of these two pre-conditions is missing, then you will likely reach a point in time when you will make the class extensible, as your code is not truly relying on abstractions.

P.S. Grazie a @ocramius per un'ottima lettura!

    
risposta data 18.11.2015 - 21:07
fonte
5

"finale" per una classe significa: vuoi una sottoclasse? Vai avanti, elimina la sottoclasse "finale" quanto vuoi, ma non lamentarti se non funziona. Sei da solo.

Quando una classe può essere sottoclassata, è il comportamento su cui gli altri fanno affidamento, deve essere descritta in termini astratti che sottoclassi obbediscono. I chiamanti devono essere scritti per aspettarsi una certa variabilità. La documentazione deve essere scritta attentamente; non puoi dire alla gente "guarda il codice sorgente" perché il codice sorgente non è ancora lì. Questo è tutto uno sforzo. Se non mi aspetto che una classe sia sottoclasse, è uno sforzo inutile. "final" dice chiaramente che questo sforzo non è stato fatto e fornisce un giusto avvertimento.

    
risposta data 18.11.2015 - 22:38
fonte
-1

Una cosa che potresti non aver pensato è che il cambiamento ANY di una classe significa che deve essere sottoposto a un nuovo test del QA.

Non contrassegnare le cose come definitive a meno che tu non lo intenda davvero sul serio.

    
risposta data 02.07.2011 - 14:12
fonte
-1

L'uso di "final" porta via la libertà degli altri che vogliono usare il tuo codice.

Se il codice che scrivi è solo per te e non verrà mai rilasciato al pubblico o a un cliente, puoi farlo con il tuo codice, ovviamente. Altrimenti, impedisci ad altri di costruire sul tuo codice. Troppo spesso ho dovuto lavorare con un'API che sarebbe stato facile estendere per le mie esigenze, ma poi sono stato ostacolato da "finale".

Inoltre, spesso c'è codice che dovrebbe non migliore essere reso private , ma protected . Certo, private significa "incapsulamento" e nasconde cose considerate come dettagli di implementazione. Ma come programmatore API posso anche documentare il fatto che il metodo xyz è considerato come dettaglio dell'implementazione e, quindi, può essere modificato / eliminato nella versione futura. Quindi chiunque faccia affidamento su tale codice nonostante l'avviso lo faccia a proprio rischio. Ma in realtà può farlo e riutilizzare (spero già testato) codice e arrivare più velocemente con una soluzione.

Naturalmente, se l'implementazione dell'API è open source, si può semplicemente rimuovere il 'final' o rendere i metodi 'protected', ma di aver modificato il codice e aver bisogno di tenere traccia delle modifiche in forma di patch.

Tuttavia, se l'implementazione è closed source, si rimane indietro nel trovare una soluzione alternativa o, nel peggiore dei casi, con il passaggio ad un'altra API con meno restrizioni riguardo alle possibilità di personalizzazione / estensione.

Notare che non trovo che "final" o "private" siano malvagi, ma penso che vengano usati troppo spesso perché il programmatore non ha pensato al suo codice in termini di riutilizzo e estensione del codice.

    
risposta data 02.07.2011 - 15:49
fonte

Leggi altre domande sui tag