it-swarm-eu.dev

Warum ist die Verwendung von 'final' in einer Klasse wirklich so schlecht?

Ich überarbeite eine PHP OOP Legacy-Website).

Ich bin so versucht, 'final' für Klassen zu verwenden, um "make it explicit that the class is currently not extended by anything ". Dies kann viel Zeit sparen, wenn ich zu einer Klasse komme und mich frage, ob ich eine protected -Eigenschaft oder -Methode umbenennen/löschen/ändern kann. Wenn ich wirklich möchte eine Klasse erweitern Ich kann einfach das letzte Schlüsselwort entfernen, um es zum Erweitern freizuschalten.

Das heißt, wenn ich zu einer Klasse komme, die keine Kinderklassen hat, kann ich dieses Wissen aufzeichnen, indem ich die Klasse als endgültig markiere. Wenn ich das nächste Mal dazu komme, müsste ich die Codebasis nicht erneut durchsuchen, um festzustellen, ob sie Kinder hat. So sparen Sie Zeit bei Refactorings.

Es scheint alles eine vernünftige zeitsparende Idee zu sein ... aber ich habe oft gelesen, dass der Unterricht nur zu seltenen/besonderen Anlässen "endgültig" sein sollte.

Vielleicht vermasselt es die Erstellung von Scheinobjekten oder hat andere Nebenwirkungen, an die ich nicht denke.

Was vermisse ich?

34
JW01

Ich habe oft gelesen, dass der Unterricht nur zu seltenen/besonderen Anlässen „endgültig“ sein sollte.

Wer das geschrieben hat, ist falsch. Verwenden Sie final großzügig, daran ist nichts auszusetzen. Es wird dokumentiert, dass eine Klasse nicht unter Berücksichtigung der Vererbung entworfen wurde. Dies gilt normalerweise standardmäßig für alle Klassen: Das Entwerfen einer Klasse, von der sinnvoll geerbt werden kann, erfordert mehr als nur das Entfernen eines final -Spezifizierers. es braucht viel Sorgfalt.

Die Verwendung von final als Standard ist also keineswegs schlecht. Tatsächlich schlagen viele Leute vor, dass dies die Standardeinstellung sein sollte, z. Jon Skeet .

Vielleicht vermasselt es die Mock-Objekterstellung ...

Dies ist in der Tat eine Einschränkung, aber Sie können jederzeit auf Schnittstellen zurückgreifen, wenn Sie Ihre Klassen verspotten müssen. Dies ist sicherlich besser, als alle Klassen nur zum Zwecke der Verspottung für die Vererbung offen zu machen.

54
Konrad Rudolph

Wenn Sie sich selbst eine Notiz hinterlassen möchten, dass eine Klasse keine Unterklassen hat, dann tun Sie dies auf jeden Fall und verwenden Sie einen Kommentar, dafür sind sie da. Das "endgültige" Schlüsselwort ist kein Kommentar, und die Verwendung von Sprachschlüsselwörtern, um Ihnen etwas zu signalisieren (und nur Sie würden jemals wissen, was es bedeutet), ist eine schlechte Idee.

8
Jeremy

Es gibt einen schönen Artikel über "Wann Klassen als endgültig deklariert werden sollen" . Ein paar Zitate daraus:

TL; DR: Machen Sie Ihre Klassen immer final, wenn sie eine Schnittstelle implementieren und keine anderen öffentlichen Methoden definiert sind

Warum muss ich final verwenden?

  1. Verhinderung einer massiven Vererbungskette von Doom
  2. Ermutigende Komposition
  3. Erzwingen Sie, dass der Entwickler über die öffentliche Benutzer-API nachdenkt
  4. Erzwingen Sie, dass der Entwickler die öffentliche API eines Objekts verkleinert
  5. Eine final Klasse kann immer erweiterbar gemacht werden
  6. extends unterbricht die Kapselung
  7. Sie brauchen diese Flexibilität nicht
  8. Sie können den Code ändern

Wann sollte man final vermeiden:

Abschlussklassen funktionieren nur unter folgenden Voraussetzungen effektiv:

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

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

P.S. Vielen Dank an @ocramius für die großartige Lektüre!

5
Nikita U.

"final" für eine Klasse bedeutet: Sie möchten eine Unterklasse? Löschen Sie das "Finale", die Unterklasse so oft Sie möchten, aber beschweren Sie sich nicht bei mir, wenn es nicht funktioniert. Du bist auf dich allein gestellt.

Wenn eine Klasse in Unterklassen unterteilt werden kann, muss das Verhalten, auf das sich andere verlassen, in abstrakten Begriffen beschrieben werden, denen Unterklassen gehorchen. Anrufer müssen geschrieben werden, um eine gewisse Variabilität zu erwarten. Die Dokumentation muss sorgfältig geschrieben werden. Sie können den Leuten nicht sagen, dass sie sich den Quellcode ansehen sollen, da der Quellcode noch nicht vorhanden ist. Das ist alles Anstrengung. Wenn ich nicht erwarte, dass eine Klasse in Unterklassen unterteilt ist, ist dies unnötiger Aufwand. "final" sagt eindeutig, dass diese Bemühungen nicht unternommen wurden und gibt eine faire Warnung.

5
gnasher729