Wann sollte Final in PHP verwendet werden?

Lesezeit: 7 Minuten

Benutzer-Avatar
Inga Johannsson

Ich weiß, was die Definition einer Final-Klasse ist, aber ich möchte wissen, wie und wann Final wirklich benötigt wird.

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

Wenn ich es richtig verstehe, ermöglicht ‘final’ es, ‘Foo’ zu erweitern.

Kann jemand erklären, wann und warum “final” verwendet werden sollte? Mit anderen Worten, gibt es einen Grund, warum eine Klasse nicht verlängert werden sollte?

Wenn beispielsweise der Klasse ‘Bar’ und der Klasse ‘Foo’ einige Funktionen fehlen, wäre es schön, eine Klasse zu erstellen, die ‘Bar’ erweitert.

Es gibt einen schönen Artikel darüber “Wann Klassen für endgültig erklärt werden”. Ein paar Zitate daraus:

TL;DR: Machen Sie Ihren Unterricht immer finalwenn sie eine Schnittstelle implementieren und keine anderen öffentlichen Methoden definiert sind

Warum muss ich verwenden final?

  1. Verhindern einer massiven Vererbungskette des Schicksals
  2. Ermutigende Komposition
  3. Zwingen Sie den Entwickler, über die öffentliche Benutzer-API nachzudenken
  4. Zwingen Sie den Entwickler, die öffentliche API eines Objekts zu verkleinern
  5. EIN final Klasse kann immer erweiterbar gemacht werden
  6. extends bricht die Kapselung
  7. Sie brauchen diese Flexibilität nicht
  8. Sie können den Code frei ändern

Wann zu vermeiden final:

Abschlussklassen funktionieren nur unter folgenden Annahmen effektiv:

  1. Es gibt eine Abstraktion (Schnittstelle), die die endgültige Klasse implementiert
  2. Die gesamte öffentliche API der letzten Klasse ist Teil dieser Schnittstelle

Wenn eine dieser beiden Vorbedingungen fehlt, werden Sie wahrscheinlich einen Zeitpunkt erreichen, an dem Sie die Klasse erweiterbar machen, da Ihr Code nicht wirklich auf Abstraktionen angewiesen ist.

PS Danke an @ocramius für das tolle Lesen!

  • Beispiel: verwenden final wenn Sie eine Utility-Klasse erstellen möchten.

    – Yousha Aleayoub

    2. Dezember 2019 um 8:06 Uhr

Benutzer-Avatar
mhanisch

Für den allgemeinen Gebrauch würde ich davon abraten, eine Klasse zu erstellen final. Es könnte einige Anwendungsfälle geben, in denen es sinnvoll ist: Wenn Sie eine komplexe API / ein komplexes Framework entwerfen und sicherstellen möchten, dass Benutzer Ihres Frameworks nur die Teile der Funktionalität überschreiben können, die sie steuern sollen, kann dies für Sie sinnvoll sein schränken Sie diese Möglichkeit ein und erstellen Sie bestimmte Basisklassen final.

zB wenn Sie eine haben Integer Klasse, es könnte Sinn machen, das zu machen final um Benutzer Ihres Framework-Formulars überschreiben zu lassen, sagen wir, die add(...) Methode in Ihrer Klasse.

  • Es hat mich in der Vergangenheit oft überrascht, wie oft ich lächerliche Dinge tun musste, die beiläufig blockiert wurden, wie Ihr Beispiel der Integer-Klasse. Zugegeben, jedes Mal, wenn es passiert ist, war es das Ergebnis wochenlanger sorgfältiger Recherche des Codes, aber es ist schon ein paar Mal passiert.

    – Iiridayn

    2. Oktober 2012 um 20:56 Uhr

  • -1: Dies ist eine reine Meinung (macht es also im Allgemeinen zu einer schlechten Antwort, da dies ein Grund wäre, die Frage stattdessen knapp abzustimmen); aber daneben wohl kein durchdachtes im sinne von programmierung. Sehen programers.stackexchange.com/q/89073/24482

    – hakre

    18. Mai 2014 um 16:15 Uhr

  • @hakre Ich sehe es rückwärts, die Frage ist diejenige, die (wie derzeit angegeben) meinungsbasierte Antworten fördert, dafür gibt es eine Flagge

    – Reinfan

    17. Juni 2017 um 22:55 Uhr

Benutzer-Avatar
li bing zhao

Der Grund sind:

  1. Das Deklarieren einer Klasse als final verhindert, dass sie in Unterklassen umgewandelt wird – Punkt; es ist das Ende der Linie.

  2. Das Deklarieren jeder Methode in einer Klasse als final ermöglicht die Erstellung von Unterklassen, die Zugriff auf die Methoden der übergeordneten Klasse haben, sie aber nicht überschreiben können. Die Unterklassen können eigene zusätzliche Methoden definieren.

  3. Das letzte Schlüsselwort steuert nur die Fähigkeit zum Überschreiben und sollte nicht mit dem privaten Sichtbarkeitsmodifikator verwechselt werden. Auf eine private Methode kann von keiner anderen Klasse zugegriffen werden; ein letztes kann.

—— zitiert von Seite 68 des Buches Objektorientierte PHP-Lösungen durch David Powers.

Zum Beispiel:

final childClassname extends ParentsClassname {
    // class definition omitted
}

Dies umfasst die gesamte Klasse, einschließlich aller ihrer Methoden und Eigenschaften. Jeder Versuch, eine untergeordnete Klasse aus childClassname zu erstellen, würde nun zu einem schwerwiegenden Fehler führen. Wenn Sie jedoch zulassen müssen, dass die Klasse abgeleitet wird, aber verhindern, dass eine bestimmte Methode überschrieben wird, steht das Schlüsselwort final vor der Methodendefinition.

class childClassname extends parentClassname { 
    protected $numPages;

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

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

In diesem Beispiel kann keiner von ihnen die überschreiben PageCount() Methode.

Benutzer-Avatar
Matt Asbury

EIN final Klasse ist eine, die nicht erweitert werden kann http://php.net/manual/en/language.oop5.final.php

Sie würden es verwenden, wenn die Klasse Methoden enthält, die Sie ausdrücklich nicht überschreiben möchten. Dies kann daran liegen, dass dies Ihre Anwendung in irgendeiner Weise beeinträchtigen würde.

Meine 2 Cent:

Wann zu verwenden final:

  • NOCH NIE!!

Wieso den?

  • Es unterbricht die Möglichkeit, Testdoubles beim Unit-Testen zu verwenden
  • aufgrund von Funktionslücken im Downstream-Code zu vermehrter Code-Duplizierung führen
  • Die Gründe für die Verwendung sind alle Trainingsprobleme, die mit einer radikalen Abkürzung angegangen werden

Schlechte Gründe, es zu verwenden:

  • Verhindern einer massiven Vererbungskette des Schicksals (Trainingsproblem)
  • Ermutigende Komposition (Trainingsproblem)
  • Zwingen Sie den Entwickler, über die öffentliche Benutzer-API nachzudenken (Trainingsproblem)
  • Zwingen Sie den Entwickler, die öffentliche API eines Objekts zu verkleinern (Schulungsproblem? Codeüberprüfungen?)
  • Eine letzte Klasse kann immer erweiterbar gemacht werden (Relevanz?)
  • erweitert die Kapselung (Was? Schlechte Kapselung bricht Kapselung; nicht Vererbung. Vererbung ist nicht von Natur aus böse.)
  • Sie brauchen diese Flexibilität nicht (typisches Denken hinter kurzsichtiger Entwicklung. Seien Sie bereit, gegen eine Feature-Wand zu stoßen + Trainingsproblem)
  • Sie können den Code frei ändern (Relevanz?)

  • Könnten Sie erklären, was Sie mit „Schulungsproblem“ meinen, da dies Ihr Hauptargument gegen die ist final Stichwort?

    – Danielle Suurlant

    30. März 2021 um 10:17 Uhr

  • Mit Verlaub, dem widerspreche ich vehement. Zunächst einmal ist es kein “Trainingsproblem” – manchmal sind die Leute, die Ihre Klasse benutzen, einfach nicht in Ihrer Verantwortung, z. B. wenn Sie eine Bibliothek schreiben, aber Sie wollen trotzdem verhindern, dass sie sich mit Vererbung in den Fuß schießen. Das Mock-Problem kann überwunden werden, indem die Klasse eine Schnittstelle implementiert und diese verspottet. Wenn ein Teil der Funktionalität wiederverwendet werden muss, kann er in eine Unterklasse oder Eigenschaft extrahiert werden, und wenn Sie eine erhebliche Menge an Code duplizieren müssen, um die Funktionalität neu zu implementieren, war die Klasse wahrscheinlich sowieso zu groß.

    – Matthew Daly

    6. April 2021 um 20:33 Uhr

  • Entschuldigung, das Refactoring heißt Klasse extrahieren, nicht Unterklasse extrahieren.

    – Matthew Daly

    6. April 2021 um 21:40 Uhr

  • Was die Flexibilität anbelangt, so kommt es wiederum oft darauf an, dass die Klasse zu viel leistet – wenn Ihre Implementierung nicht flexibel genug ist, ohne erweitert zu werden, macht sie wahrscheinlich zu viel und Sie sollten erwägen, einen Teil der Funktionalität in separate Klassen umzugestalten. Und für einige Verhaltensänderungen wie das Hinzufügen von Caching oder Protokollierung ist das Dekorieren der Klasse eine bessere Methode, die nicht an diese Implementierung gebunden ist und die neue Funktionalität getrennt hält.

    – Matthew Daly

    6. April 2021 um 22:46 Uhr

  • “Trainingsproblem” bedeutet, dass es wirklich kein Codierungsproblem ist, sondern ein Problem der Menschen. rede mit den leuten. besser dokumentieren. häufig Designdiskussionen führen.

    – Johannes Braun

    27. Mai 2021 um 0:06 Uhr

  • Könnten Sie erklären, was Sie mit „Schulungsproblem“ meinen, da dies Ihr Hauptargument gegen die ist final Stichwort?

    – Danielle Suurlant

    30. März 2021 um 10:17 Uhr

  • Mit Verlaub, dem widerspreche ich vehement. Zunächst einmal ist es kein “Trainingsproblem” – manchmal sind die Leute, die Ihre Klasse benutzen, einfach nicht in Ihrer Verantwortung, z. B. wenn Sie eine Bibliothek schreiben, aber Sie wollen trotzdem verhindern, dass sie sich mit Vererbung in den Fuß schießen. Das Mock-Problem kann überwunden werden, indem die Klasse eine Schnittstelle implementiert und diese verspottet. Wenn ein Teil der Funktionalität wiederverwendet werden muss, kann er in eine Unterklasse oder Eigenschaft extrahiert werden, und wenn Sie eine erhebliche Menge an Code duplizieren müssen, um die Funktionalität neu zu implementieren, war die Klasse wahrscheinlich sowieso zu groß.

    – Matthew Daly

    6. April 2021 um 20:33 Uhr

  • Entschuldigung, das Refactoring heißt Klasse extrahieren, nicht Unterklasse extrahieren.

    – Matthew Daly

    6. April 2021 um 21:40 Uhr

  • Was die Flexibilität anbelangt, so kommt es wiederum oft darauf an, dass die Klasse zu viel leistet – wenn Ihre Implementierung nicht flexibel genug ist, ohne erweitert zu werden, macht sie wahrscheinlich zu viel und Sie sollten erwägen, einen Teil der Funktionalität in separate Klassen umzugestalten. Und für einige Verhaltensänderungen wie das Hinzufügen von Caching oder Protokollierung ist das Dekorieren der Klasse eine bessere Methode, die nicht an diese Implementierung gebunden ist und die neue Funktionalität getrennt hält.

    – Matthew Daly

    6. April 2021 um 22:46 Uhr

  • “Trainingsproblem” bedeutet, dass es wirklich kein Codierungsproblem ist, sondern ein Problem der Menschen. rede mit den leuten. besser dokumentieren. häufig Designdiskussionen führen.

    – Johannes Braun

    27. Mai 2021 um 0:06 Uhr

1335130cookie-checkWann sollte Final in PHP verwendet werden?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy