Când să utilizați Final în PHP? (Programare, Php, Oop, Final)

Inga Johansson a intrebat.

Știu care este definiția unei clase Final, dar vreau să știu cum și când este cu adevărat necesar.

<?php
final class Foo extends Bar
{
   public function()
   {
     echo 'John Doe';
   }
}

Dacă înțeleg corect, „final” îi permite să extindă „Foo”.

Poate cineva să explice când și de ce ar trebui să se folosească „final”? Cu alte cuvinte, există vreun motiv pentru care o clasă nu ar trebui să fie extinsă?

Dacă, de exemplu, clasei „Bar” și clasei „Foo” le lipsește o anumită funcționalitate, ar fi bine să se creeze o clasă care să extindă „Bar”.

5 răspunsuri
mhanisch

Pentru utilizarea generală, aș recomanda să nu faceți o clasă final. Ar putea exista unele cazuri de utilizare în care are sens: dacă proiectați un API / cadru complex și doriți să vă asigurați că utilizatorii cadrului dvs. pot suprascrie numai părțile de funcționalitate pe care doriți să le controleze, ar putea avea sens să restricționați această posibilitate și să faceți anumite clase de bază final.

De exemplu, dacă aveți o clasă Integer ar putea avea sens să faceți ca această clasă final pentru ca utilizatorii cadrului dvs. să nu poată suprascrie, de exemplu, clasa add(...) din clasa dumneavoastră.

Comentarii

  • M-a surprins adesea în trecut cât de des am fost nevoit să fac lucruri ridicole care erau blocate întâmplător, cum ar fi exemplul clasei Integer. Desigur, de fiecare dată când s-a întâmplat, a fost produsul unor săptămâni de cercetare atentă a codului, dar s-a întâmplat deja de câteva ori. –  > Por Iiridayn.
  • -1: Aceasta este o opinie pură (ceea ce o face, în general, un răspuns prost, deoarece acesta ar fi un motiv pentru a închide votul la întrebare în schimb); dar, pe lângă asta, cel mai probabil nu este unul chibzuit în sensul programării. A se vedea programmers.stackexchange.com/q/89073/24482 –  > Por hakre.
  • @hakre Eu văd lucrurile invers, întrebarea este cea care (așa cum este formulată în prezent) încurajează răspunsurile bazate pe opinii, există un indicator pentru acest lucru –  > Por Purefan.
Nikita U.

Există un articol frumos despre „Când să declarăm clasele finale”. Câteva citate din el:

TL;DR: Faceți clasele dvs. întotdeauna final, dacă implementează o interfață și nu sunt definite alte metode publice.

De ce trebuie să folosesc final?

  1. Prevenirea lanțului masiv de moștenire a condamnării prin moștenire
  2. Încurajarea compoziției
  3. Forțarea dezvoltatorului să se gândească la API-ul public al utilizatorului
  4. Forțați dezvoltatorul să micșoreze API-ul public al unui obiect
  5. A final clasă poate fi întotdeauna extinsă
  6. extends rupe încapsularea
  7. Nu aveți nevoie de această flexibilitate
  8. Sunteți liber să modificați codul

Când trebuie evitată final:

Clasele finale funcționează eficient numai în următoarele ipoteze:

  1. există o abstracțiune (interfață) pe care clasa finală o implementează.
  2. întreaga API publică a clasei finale face parte din acea interfață.

Dacă lipsește una dintre aceste două condiții prealabile, atunci probabil că veți ajunge la un moment dat când veți face clasa extensibilă, deoarece codul dumneavoastră nu se bazează cu adevărat pe abstracțiuni.

P.S. Mulțumesc lui @ocramius pentru o lectură excelentă!

Comentarii

  • Exemplu: use final atunci când doriți să creați o clasă de utilitate. –  > Por Yousha Aleayoub.
li bing zhao

Motivul sunt:

  1. Declararea unei clase ca fiind finală o împiedică să fie subclasată – punct; este un capăt de linie.

  2. Declararea fiecărei metode dintr-o clasă ca finală permite crearea de subclase, care au acces la metodele clasei părinte, dar nu le pot suprascrie. Subclasele pot defini metode proprii suplimentare.

  3. Cuvântul cheie final controlează doar capacitatea de a suprascrie și nu trebuie confundat cu modificatorul de vizibilitate privată. O metodă privată nu poate fi accesată de nicio altă clasă; o metodă finală poate fi accesată.

— citat de la pagina 68 a cărții Soluții PHP orientate pe obiecte de David Powers.

De exemplu:

final childClassname extends ParentsClassname {
    // class definition omitted
}

Aceasta acoperă întreaga clasă, inclusiv toate metodele și proprietățile sale. Orice încercare de a crea o clasă copil din childClassname ar avea acum ca rezultat o eroare fatală. Dar, dacă trebuie să permiteți ca clasa să fie subclasată, dar să împiedicați suprapunerea unei anumite metode, cuvântul cheie final se pune în fața definiției metodei.

class childClassname extends parentClassname { 
    protected $numPages;

    public function __construct($autor, $pages) {
        $this->_autor = $autor;
        $this->numPages = $pages;
    }

    final public function PageCount() { 
        return $this->numPages; 
    }
}

În acest exemplu, niciunul dintre ei nu va putea suprascrie metoda PageCount() metoda.

Matt Asbury

A final clasă este o clasă care nu poate fi extinsă http://php.net/manual/en/language.oop5.final.php

Ați folosi-o în cazul în care clasa conține metode pe care nu doriți să le suprascrieți. Acest lucru se poate datora faptului că, dacă o faceți, aplicația dumneavoastră s-ar strica într-un fel sau altul.

Comentarii

  • Îmi pare rău, dar nu aceasta era întrebarea mea. –  > Por Inga Johansson.
  • Îmi pare rău că m-am lăsat dus de val cu butonul de trimitere. Editat. Vă rog să mă anunțați dacă doriți să dezvolt –  > Por Matt Asbury.
  • Da, a fost: „Dacă am înțeles corect, „final permite să extindă „Foo”.” –  > Por Malfist.
  • You would use it where the class contained methods which you specifically do not want overridden. This may be because doing do would break your application in some way. Ați putea da un exemplu? În loc de overriding, extinderea ar putea, de asemenea, să adauge funcționalitate în loc de overriding, sau…? –  > Por Inga Johansson.
  • @Gumbo, vreau doar să știu dacă crearea de clase finale este o practică greșită, iar manualul PHP nu-mi spune acest lucru. Poți să-mi spui unde pot găsi asta? –  > Por Inga Johansson.
John Brown

Cei 2 cenți ai mei:

Când să utilizați final:

  • NICIODATĂ!!!

De ce?

  • întrerupe capacitatea de a utiliza teste duble atunci când se testează unitar
  • ar putea duce la creșterea duplicării codului din cauza lacunelor de funcționalitate în codul din aval
  • motivele pentru a o utiliza sunt toate problemele de formare care sunt abordate cu o scurtătură radicală

Motive proaste pentru a-l utiliza:

  • Împiedicarea lanțului de moștenire masivă a moștenirii de nenorocire (problemă de formare)
  • Încurajarea compoziției (problemă de formare)
  • Forțarea dezvoltatorului să se gândească la API-ul public al utilizatorului (problemă de formare)
  • Forțarea dezvoltatorului să micșoreze API-ul public al unui obiect (problemă de formare? revizuiri de cod?)
  • O clasă finală poate fi întotdeauna extinsă (relevanță?)
  • extensia rupe încapsularea (ce? o încapsulare slabă rupe încapsularea; nu și moștenirea. moștenirea nu este în mod inerent rea.)
  • Nu aveți nevoie de această flexibilitate (gândire tipică din spatele dezvoltării cu viziune scurtă. fiți pregătiți să vă loviți de un zid de caracteristici + o problemă de formare)
  • Sunteți liber să modificați codul (relevanță?)

Tags:, ,