Wie kann das Entwerfen für die Vererbung zusätzliche Kosten verursachen? [geschlossen]


12

Also wollte ich von a sealed classin csharp erben und wurde verbrannt. Es gibt nur eine Möglichkeit, die Versiegelung aufzuheben, wenn Sie Zugriff auf die Quelle haben.

Dann dachte ich: "Warum sealedgibt es überhaupt?" vor 4 Monaten. Ich konnte es nicht herausfinden, obwohl ich viele Dinge darüber gelesen habe, wie zum Beispiel:

Ich habe seitdem versucht, das alles zu verdauen, aber es ist einfach zu viel für mich. Irgendwann gestern habe ich es nochmal versucht. Ich habe sie alle noch einmal gescannt und noch ein paar mehr:

Schließlich habe ich mich nach langem Nachdenken entschlossen , die ursprüngliche Frage auf der Grundlage des neuen Titels stark zu bearbeiten.

Die alte Frage war zu weit gefasst und subjektiv. Grundsätzlich wurde gefragt:

  1. Im alten Titel: Ein guter Grund, versiegelt zu verwenden
  2. Im Körper: Wie kann man eine versiegelte Klasse richtig modifizieren? Erbschaft vergessen? Komposition verwenden?

Aber jetzt, zu verstehen (was ich nicht gestern) , dass alles sealedtut , ist Vererbung zu verhindern , und wir können und in der Tat verwenden sollten Komposition der Vererbung , wurde mir klar , was ich brauchte , war praktische Beispiele.

Ich denke, meine Frage hier ist genau das, was Mr.Mindor mir in einem Chat vorgeschlagen hat (und das war es auch schon immer) : Wie kann das Entwerfen für die Vererbung zusätzliche Kosten verursachen?


5
Die Frage ist ziemlich aggressiv formuliert und klingt wie ein Scherz. Sie sollten es umformulieren, wenn Sie relevante und objektive Antworten wünschen.
Euphoric

11
Sehen Sie, warum so viele Framework-Klassen versiegelt sind. von Eric Lippert. Er bietet mehrere gute Gründe, um Klassen zu besiegeln.
Robert Harvey

9
Dann hast du den Artikel nicht gelesen. Geh zurück und lies es noch einmal. Es läuft darauf hinaus, dass Sie nicht vorhersagen können, auf welche Weise ein Client Ihre Klasse durch eine Erweiterung unterbrechen könnte. Sie können Ihren Kunden die Schuld dafür geben, aber Sie müssen sie unterstützen.
Robert Harvey

4
@ Kawas Er könnte, oder Sie könnten den Artikel, den er verlinkt hat, lesen, der es im Detail erklärt. Er fasste diesen Artikel nur mit seinem Kommentar zusammen.
Servy

7
Entschuldigung, aber ich bin nicht derjenige, der hier schimpft. Die Antwort auf Ihre Frage ist ganz einfach: Versiegeln Sie eine Klasse, wenn Sie die Vererbung nicht unterstützen möchten. Das ist es.
Robert Harvey

Antworten:


27

Das ist nicht so schwer zu verstehen. sealedwurde SPEZIELL für Microsoft entwickelt, um ihr Leben zu erleichtern, viel Geld zu sparen und ihren Ruf zu verbessern. Da es sich um ein Sprachfeature handelt, kann es auch jeder andere verwenden, aber DU wirst es wahrscheinlich nie brauchen, Sealed zu verwenden.

Die meisten Leute beschweren sich darüber, dass sie eine Klasse nicht erweitern können, und wenn sie dies tun, sagen sie, dass jeder weiß, dass die Entwickler dafür verantwortlich sind, dass sie richtig funktionieren. Das ist richtig, mit AUSNAHME, dass dieselben Leute keine Ahnung von der Geschichte von Windows haben und eines der Probleme sealedzu lösen versucht.

Nehmen wir an, ein Entwickler hat eine .Net-Core-Klasse erweitert (weil sie nicht vorhanden war) und dafür gesorgt, dass sie perfekt funktioniert. Ja, für den Entwickler. Der Entwickler liefert das Produkt an den Kunden. Die Entwickler-App funktioniert hervorragend. Der Kunde ist glücklich. Das leben ist gut.

Jetzt veröffentlicht Microsoft ein neues Betriebssystem, das das Beheben von Fehlern in dieser speziellen .NET-Core-Klasse umfasst. Der Kunde möchte mit der Zeit gehen und wählt die Installation des neuen Betriebssystems. Plötzlich funktioniert die Anwendung, die dem Kunden so gut gefällt, nicht mehr, da die in der .Net-Core-Klasse behobenen Fehler nicht berücksichtigt wurden.

Wer wird dafür verantwortlich gemacht?

Diejenigen, die mit der Geschichte von Microsoft vertraut sind, wissen, dass das neue Betriebssystem von Microsoft die Schuld trägt und nicht die Anwendungssoftware, die Windows-Bibliotheken missbraucht hat. Dann muss Microsoft das Problem beheben und nicht das Anwendungsunternehmen, das das Problem erstellt hat. Dies ist einer der Gründe, warum Windows-Code aufgebläht wurde. Nach dem, was ich gelesen habe, ist der Windows-Betriebssystemcode mit einem bestimmten Wenn-Dann-Code übersät, der prüft, ob eine bestimmte Anwendung und Version ausgeführt wird. Wenn ja, führen Sie eine spezielle Verarbeitung durch, damit das Programm funktioniert. Das ist eine Menge Geld, das von Microsoft ausgegeben wird, um die Inkompetenz eines anderen Unternehmens zu beheben.

Die Verwendung von sealedbeseitigt das obige Szenario nicht vollständig, hilft jedoch.


4
@ Kawas Es ist ziemlich schwer, es zu missbrauchen. Eric Lippert hat mehrmals angegeben, dass Klassen wie auch Methoden sealedstandardmäßig verwendet werden, es sei denn, sie wurden speziell entsiegelt, nur weil so wenige Klassen tatsächlich für die Vererbung entworfen wurden. Es ist viel wahrscheinlicher, dass Ihre Klasse nicht dafür gebaut wurde, dies zu unterstützen, und Sie sollten sicherstellen, dass Sie diese Entwicklungszeit verbracht haben, wenn Sie sich Mühe geben, sie als nicht versiegelt zu markieren.
Servy

1
Ich denke, wenn Leute Sealed für ihre interne Entwicklungssoftware verwenden, missbrauchen sie es wahrscheinlich oder verschwenden nur Zeit, um zu perfekt zu sein. Ich sage wahrscheinlich, weil es immer Fälle gibt, die in einem bestimmten Szenario sinnvoll sind. Ich würde jedoch vermuten, dass es für diejenigen, die Software vom Typ Bibliothek entwickeln, aus den gleichen Gründen sehr nützlich ist, aus denen Microsoft den Schluss gezogen hat, dass dies erforderlich ist.
Dunk

2
@Cawas Die allermeisten Klassen, die von den meisten Entwicklern geschrieben wurden, müssen niemals geerbt werden und werden nicht zur Unterstützung der Vererbung geschrieben. Dies kann schnell und effektiv an Leser / Benutzer des Codes weitergegeben werden, indem der Typ angegeben wird sealed. Wenn es tatsächlich die Standardoption wäre, würde dies bedeuten, dass jemand, der von einem Typ erbt, weiß, dass er dafür gebaut ist.
Servy

2
Das Entsiegeln einer Klasse bedeutet nicht, dass die Klasse zur Unterstützung dieser Klasse erstellt wurde. Es bedeutet nur, dass jemand von der Klasse erben und sie entsiegeln wollte. Im besten Fall führt die Verwendung von Sealed dazu, dass Entwickler vorhandene Funktionen (die der Sealed-Klasse entsprechen) neu schreiben. Wenn der Quellcode jedoch verfügbar ist, wird er in den meisten Fällen einfach entsiegelt, ohne die Konsequenzen zu berücksichtigen. Es ist besser, dass seal spezifisch und selten gesetzt ist, denn dann möchte der Entwickler möglicherweise herausfinden, warum diese Klasse seal ist. Zu viele versiegelte Klassen, und es ist ihnen egal, warum.
Dunk

1
Auch Sicherheit ist ein Grund , es zu benutzen! Stellen Sie sich eine Sandbox-Anwendung vor, die versucht, auf eine Datei zuzugreifen. Die Sandbox könnte die Dateinamen-Strings testen, aber was ist, wenn ein Angreifer Ihnen eine veränderbare Datei senden könnte Stringund diese dann nach der Sicherheitsprüfung, aber vor der E / A-Operation verändert? Ich glaube, diese Art von Szenario ist der Grund, warum Java Stringmarkiert ist final(ähnlich wie sealed) und ich wette, dass die gleiche Logik einige C # -Entscheidungen untermauert.
Darien

23

sealedwird verwendet, um anzuzeigen, dass der Schreiber der Klasse die Vererbung nicht geplant hat. Nicht weniger, nicht mehr.

Das richtige Entwerfen einer Schnittstelle ist für viele Programmierer bereits schwierig genug. Das ordnungsgemäße Entwerfen einer Klasse, die möglicherweise vererbt werden kann, fügt Schwierigkeiten und Codezeilen hinzu. Mehr geschriebene Codezeilen bedeuten mehr zu wartenden Code. Um diese zunehmende Schwierigkeit zu vermeiden, sealedkönnen Sie nachweisen, dass die Klasse nie vererbt werden sollte. In diesem Zusammenhang ist das Versiegeln einer Klasse eine einwandfreie Lösung für ein Problem .

Stellen Sie sich den Fall vor, von dem die Klasse CustomBoeing787abgeleitet ist Airliner. Dies CustomBoeing787setzt einige geschützte Methoden außer Kraft Airliner, jedoch nicht alle. Wenn der Entwickler genügend Zeit hat und es sich lohnt, kann er die Klasse einzeln testen, um sicherzustellen, dass alles wie erwartet funktioniert, auch in einem Kontext, in dem nicht überschriebene Methoden aufgerufen werden (z. B. geschützte Setter, die den Status des Objekts ändern). Wenn derselbe Entwickler (1) keine Zeit hat, (2) keine zusätzlichen Hunderte oder Tausende von Dollar für seinen Chef / Kunden ausgeben möchte oder (3) keinen zusätzlichen Code schreiben möchte, den er nicht hat brauche jetzt (YAGNI), dann kann er:

  • Geben Sie den Code entweder so frei, wie er ist, da es das Anliegen der Programmierer ist, dieses Projekt später zu warten, um mögliche Fehler zu beheben.

  • oder markieren Sie die Klasse sealed, um den zukünftigen Programmierern explizit anzuzeigen, dass diese Klasse nicht geerbt werden soll und dass das Entsiegeln und Verwenden der Klasse als übergeordnetes Element auf eigenes Risiko erfolgen sollte.

Ist es eine gute Idee, so viele Klassen wie möglich oder so wenige wie möglich zu besiegeln? Aus meiner Erfahrung gibt es keine endgültige Antwort. Einige Entwickler neigen dazu, sealedzu viel zu verwenden. Anderen ist es egal, wie die Klasse vererbt wird und welches Problem sie verursachen kann. Bei einer solchen Verwendung ähnelt das Problem demjenigen, bei dem bestimmt wird, ob Programmierer zwei oder vier Leerzeichen zum Einrücken verwenden sollen: Es gibt keine richtige Antwort.


In Ordnung ... Entschuldigung, wenn ich wieder aggressiv klinge, aber ich möchte hier nur klar und bestimmt sein ... Ich kann nur verstehen, was Sie gerade auf zwei Arten geschrieben haben, wenn Sie hier eine schreiben würden tl;dr. Entweder "Nein, es gibt keinen guten Grund" oder "Ich glaube, es gibt keinen guten Grund, aber ich weiß es auch nicht." . Für mich ist "keine endgültige Antwort" eine davon.
Cregox

6
sealedwird verwendet, um anzuzeigen, dass der Schreiber der Klasse die Vererbung nicht geplant hat. Das ist dein einziger guter Grund.
Robert Harvey

Das ist so ein guter Grund, als ob Sie ein Fahrrad ohne Lichter bekommen und irgendwie keine Lichter hinzufügen können.
Cregox

2
@ Kawas Wie so? In diesem Zusammenhang ist es für den Fahrradbauer nicht wichtig , um sicherzustellen , dass das Fahrrad kein Licht hat, aber es oft ist wichtig , dass der Benutzer eines Typs , um sicherzustellen , dass die Umsetzung eine besondere genaue Umsetzung ist. Sie erzwingen die Einschränkungen, die Sie benötigen. In einigen Fällen können Benutzer eine Einschränkung hinzufügen, die tatsächlich nicht benötigt wird. Sie haben ein Beispiel dafür angegeben. Nur weil die Einschränkung an einem Ort missbraucht wird, heißt das nicht, dass Sie niemals irgendetwas einschränken sollten.
Servy

1
Auch Sicherheit ist ein Grund , es zu benutzen! Stellen Sie sich eine Sandbox-Anwendung vor, die versucht, auf eine Datei zuzugreifen. Die Sandbox könnte die Dateinamen-Strings testen, aber was ist, wenn ein Angreifer Ihnen eine veränderbare Datei senden könnte Stringund diese dann nach der Sicherheitsprüfung, aber vor der E / A-Operation verändert? Ich glaube, diese Art von Szenario ist der Grund, warum Java Stringmarkiert ist final(ähnlich wie sealed) und ich wette, dass die gleiche Logik einige C # -Entscheidungen untermauert.
Darien

4

Wenn eine Klasse versiegelt ist, kann Code, der diesen Typ verwendet, genau wissen, womit sie zu tun haben.

Jetzt in C # stringist sealed, können Sie nicht davon erben, aber nehmen wir für eine Sekunde an, dass das nicht der Fall war. Wenn Sie das getan haben, könnte jemand eine Klasse wie diese schreiben:

public class EvilString// : String
{
    public override string ToString()
    {
        throw new Exception("I'm mean");
    }
    public override bool Equals(object obj)
    {
        return false;
    }
    public override int GetHashCode()
    {
        return 0;
    }
}

Dies wäre nun eine Zeichenfolgenklasse, die alle Arten von Eigenschaften verletzt, von denen die Designer stringwussten, dass sie wahr sind. Sie wussten, dass die EqualsMethode transitiv sein würde, das ist nicht. Heck, diese Gleichheitsmethode ist nicht einmal symmetrisch, da eine Zeichenfolge gleich sein könnte, aber es wäre nicht gleich zu dieser Zeichenfolge. Ich bin sicher, dass es alle Arten von Programmierern gibt, die Code unter der Annahme geschrieben haben, dass die ToStringMethode von stringkeine Ausnahme für Nicht-Null-Werte auslöst. Sie können jetzt diese Annahme verletzen.

Es gibt eine beliebige Anzahl anderer Klassen, für die wir dies tun könnten, und alle möglichen anderen Annahmen, gegen die wir verstoßen könnten. Wenn Sie die Sprachfunktion für entfernensealeddann müssen die Sprachdesigner jetzt damit beginnen, solche Dinge in ihrem gesamten Bibliothekscode zu berücksichtigen. Sie müssen alle Arten von Überprüfungen durchführen, um sicherzustellen, dass erweiterte Typen der Typen, die sie verwenden möchten, "richtig" geschrieben werden, was eine sehr teure Sache sein kann (sowohl in der Entwicklungszeit als auch zur Laufzeit). Indem sie eine Klasse versiegeln können, können sie sicherstellen, dass dies nicht möglich ist und dass Aussagen zu den Implementierungsdetails ihrer eigenen Typen nicht verletzt werden können, mit Ausnahme der Typen, die absichtlich erweitert werden sollen. Für die Typen, die erweitert werden sollen, muss der Sprachcode wesentlich defensiver im Umgang mit ihnen sein.


Sie können jedoch gegen diese Annahme in Ihrem Code verstoßen . Es ist nicht so, als würden Sie die Quelle von String greifen und bearbeiten. Die Designer müssten dies nicht berücksichtigen, da es sich um 1 Blatt, 1 Zweig, 1 Client handelt, der es auf eigenes Risiko und nach eigenem Ermessen verwendet. Von dort aus wird es nicht verbreitet, es sei denn, andere Kunden bevorzugen dies. Und so weiter.
Cregox

3
@Cawas Und wenn eine Ausnahme zu einem unerwarteten Zeitpunkt ausgelöst wird und dadurch eine Ressource verloren geht oder eine Klasse in einem unbestimmten Zustand belassen wird und unangemessen funktioniert? Dieser Fall ist ein bisschen albern, aber es kann leicht vorkommen, dass jemand eine Implementierung schreibt, die er für sinnvoll hält, aber gelegentlich auslöst, wenn dies nicht der Fall sein sollte oder mit bestimmten Werten nicht funktioniert. Sie beschweren sich dann, wenn der Sprachcode nicht funktioniert. Es ist vorzuziehen, die Leute nicht Dinge tun zu lassen, die die Sprache nicht unterstützen kann.
Servy

In jedem Fall geht es um das Erstellen eines Compilers. Es sind viele solcher sealedFunktionen eingebaut, die für uns nicht zugänglich sind. Es erklärt immer noch nicht, warum es außerhalb eines so engen Rahmens verwendet wird, und da es so eng wie Compiler-Code ist , erklärt es nicht einmal die sealedExistenz.
Cregox

2
@Cawas Der stringTyp ist kein Compiler-Code. Es ist Teil des Sprachcodes. Ganz anders. Auf jeden Fall habe ich nur ein Beispiel ausgewählt. Sie könnten fast jede versiegelte Klasse in der gesamten BCL aufnehmen und dies als Beispiel verwenden.
Servy

4
@ Kawas: Ich denke, was Sie hier vermissen, ist der Aspekt der Kundenbetreuung. Wenn Sie zulassen, dass eine Klasse vererbbar ist, werden Kunden die Klasse erben und Sie dann anrufen, wenn sie kaputt geht. Sie können ihnen den ganzen Tag sagen, dass sie auf eigenes Risiko von dieser Klasse erben , aber Sie werden trotzdem den Anruf erhalten, weil Sie ihnen erlaubt haben, von ihr zu erben, und sie davon ausgehen, dass dies sicher ist.
Robert Harvey

3

Gibt es einen guten Grund, versiegelt zu verwenden?

Enh? Nicht oft. Ich werde nur versiegelt verwendet , wenn ich eine unveränderliche Art haben (oder eine andere Begrenzung) , die wirklich wirklich unveränderlich bleiben muss und kann ich nicht vertrauen Erben diese Anforderung furfill ohne Einführung subtil, catastropic Fehler in das System.

Angenommen, es gibt einen guten Grund, Sealed zu verwenden, und wir sollten es als Standard für alles verwenden, was wir mit Vererbung tun.

Wir verwenden die Vererbung für diejenigen Dinge, die nicht standardmäßig sind. Selbst wenn die Komposition der Vererbung vorgezogen wird (und dies auch ist), bedeutet dies nicht, dass die Vererbung verworfen werden muss. Dies bedeutet, dass die Vererbung einige intrinsische Probleme hat, die sie in die Design- und Code-Wartbarkeit einführt, und dass die Komposition (im Allgemeinen) mit weniger Problemen dasselbe bewirkt. Und es bedeutet, dass selbst wenn die Komposition bevorzugt wird, die Vererbung für bestimmte Teilmengen von Problemen gut ist.

Ich meine nicht sein zu gemein , aber wenn Sie schon jetzt nur noch fester und Unit - Tests gehören, sollten Sie vielleicht aus underneith Ihrem Rock raus und tatsächlich Code schreiben. Die Dinge sind nicht eindeutig und in den seltensten Fällen ist "immer X tun" oder "niemals Y verwenden" oder "Z ist am besten" der richtige Weg (wie es scheint, dass Sie aufgrund der Ansichten Ihrer Frage dazu tendieren). Während Sie Code schreiben, können Sie Fälle sehen, in denen sealedes gut sein könnte, und Fälle, in denen es Sie betrübt - genau wie bei jedem anderen Kompromiss.


Für mich sind dies und das "Vermeiden, die Vererbung an Kunden unterstützen zu müssen", das Robert nicht näher erläutern möchte, die vielversprechendsten Antworten sealed.
Cregox

@ Kawas - Ich bin nicht sicher, ob ich gut kann. Ich mache es sehr selten und es ist oft ein Kompromiss, wenn die Garantie, dass etwas unveränderlich bleibt (um Leistungsoptimierungen vorzunehmen, Designvereinfachungen), die Unfähigkeit wert ist, vom Objekt zu erben.
Telastyn

Das ist cool. Dunk hat es bereits getaucht! : P Vielen Dank für die Antwort. Und Sie waren der einzige, der meine "subtilen Hinweise" zu meinem Fachwissen aufgegriffen hat. Es scheint, als würden die Leute annehmen, ich wüsste mehr, ich weiß nicht ... Aber ich wünschte, "nur Codierung" würde mich aus diesem Felsen herausholen. Vielleicht wende ich diese Konzepte auf irgendeine Weise an, nur nicht so prozedural, wie ich es wahrscheinlich sollte.
Cregox

3

Lesen Sie zunächst den Beitrag von Eric Lippert, warum Microsoft ihre Klassen besiegelt.

http://blogs.msdn.com/b/ericlippert/archive/2004/01/22/61803.aspx

Zweitens existiert das versiegelte Schlüsselwort, um genau das zu tun, was es tut - die Vererbung zu verhindern. Es gibt viele Situationen, in denen Sie die Vererbung verhindern möchten. Stellen Sie sich eine Klasse vor, für die Sie eine Sammlung haben. Wenn Ihr Code davon abhängt, dass diese Klasse auf bestimmte Weise funktioniert, möchten Sie nicht, dass jemand eine der Methoden oder Eigenschaften in dieser Klasse überschreibt und das Fehlschlagen Ihrer Anwendung verursacht.

Drittens fördert die Verwendung von Sealed die Komposition gegenüber der Vererbung, was eine gute Angewohnheit ist. Die Verwendung von Komposition anstelle von Vererbung bedeutet, dass Sie nicht gegen Liskovs Substitutionsprinzip verstoßen können und dem Open / Closed-Prinzip folgen. sealedist daher ein Schlüsselwort, das Sie dabei unterstützt, zwei der fünf wichtigsten Prinzipien der oo-Programmierung zu befolgen. Ich würde sagen, das macht es zu einem sehr wertvollen Feature.


Auf den ersten Teil wird bereits in den Fragenkommentaren hingewiesen. Der zweite Teil ist nur eine Argumentation ohne wirkliche Ursachen. Der dritte Teil, auch wenn er bereits an anderer Stelle behandelt wurde, könnte etwas damit zu tun haben. Darauf würde ich mich konzentrieren.
Cregox

Der dritte Punkt fördert nicht die Komposition über die Vererbung, sondern beseitigt die Vererbung als Option vollständig, selbst wenn dies die beste Wahl insgesamt war.
Michael Shaw

Das hängt davon ab, ob Sie die Codebasis steuern oder nicht. Wenn Sie Klassen versiegeln, können Sie sie später bei Bedarf jederzeit wieder entsiegeln.
Stephen

2

Ich denke, dass diese Frage keine objektive Antwort hat und dass alles von Ihrer Perspektive abhängt.

Eine Seite, einige Leute wollen, dass alles "offen" ist, und die Verantwortung dafür, dass alles richtig funktioniert, liegt bei der Person, die die Klasse erweitert. Aus diesem Grund können Klassen standardmäßig vererbt werden. Und warum Java-Methoden standardmäßig alle virtuell sind.

Auf der anderen Seite möchten einige, dass standardmäßig alles geschlossen ist und Optionen zum Öffnen bereitgestellt werden. In diesem Fall ist es der Autor der Basisklasse, der sicherstellen muss, dass alles, was er "offen" macht, in jeder erdenklichen Weise sicher zu gebrauchen ist. Aus diesem Grund sind in C # alle Methoden standardmäßig nicht virtuell und müssen zum Überschreiben als virtuell deklariert werden. Es ist auch für diejenigen Menschen, die "offene" Vorgaben umgehen müssen. Als würde man die Klasse versiegelt / final machen, weil sie sehen, dass jemand, der von der Klasse abstammt, ein großes Problem für das Design ihrer eigenen Klasse ist.


So ist es besser! Dies könnte ein guter Grund sein ... "Weil die Leute es schließen wollen". Und es ist auch das, was ich in der Frage zu sagen versuche: Es sieht so aus, als ob nicht virtuelle Klassen in C ++ überschrieben werden können. sealedkippen. Wie können wir von ihnen erben? Ich lese nur, dass wir es nicht können. Je. Ich weiß es nicht. Ich bin jetzt seit 4 Monaten auf und ab gegangen, seit ich zum ersten Mal von Sealed gehört habe. Und ich weiß noch nicht , wie es richtig zu tun , wenn ich brauche etwas auf einer versiegelte Klasse zu ändern. Also sehe ich keine "Option zum Öffnen"!
Cregox

4
Dies ist nicht der Grund, warum C ++ - Klassenmethoden standardmäßig nicht virtuell sind. Wenn Sie eine Methode virtuell machen, muss die Methodensuchtabelle zusätzlichen Overhead aufweisen. In C ++ gilt die Philosophie, dass Sie den Overhead nur bezahlen, wenn Sie das Feature möchten.
Michael Shaw

@Ptolemy Ok, ich habe es entfernt. Ich hätte es nie schreiben sollen, weil ich wusste, dass sich die Leute darüber beschweren.
Euphoric

hey, ich weiß das zu schätzen, wenn du behaupten willst, dass Leute standardmäßig geschlossene Klassen schreiben wollen und sie aktiv öffnen müssen, dann musst du dich an Strohhalme klammern
Michael Shaw

IMO ist es den privaten / geschützten / öffentlichen Debatten sehr ähnlich, wenn es um APIs geht: Es hängt stark davon ab, wer die Klasse kontrolliert, wer die Klasse erben möchte, wie oft neue Versionen herauskommen.
Darien

-2

Das Problem mit Sealed in C # ist, dass es ziemlich endgültig ist. In den 7 Jahren der kommerziellen C # -Entwicklung wurde es nur in Microsoft .NET-Klassen verwendet, in denen meines Erachtens ein legitimer Grund dafür bestand, eine Framework-Klasse zu erweitern, um angepasstes Verhalten zu implementieren. Da die Klasse versiegelt war, konnte ich dies nicht .

Es ist unmöglich, eine Klasse zu schreiben, die über jede mögliche Verwendung nachdenkt und entscheidet, dass keine von ihnen legitim ist. Wenn die Framework-Sicherheit davon abhängig ist, dass die Klasse nicht vererbt wird, liegt ebenfalls ein Sicherheitsentwurfsfehler vor.

Zusammenfassend bin ich also der festen Überzeugung, dass versiegelt keinen nützlichen Zweck erfüllt, und nichts, was ich bisher hier gelesen habe, hat diese Ansicht geändert.

Ich kann sehen, dass es bisher drei Argumente gegeben hat, die das bisher Gesiegelte rechtfertigen.

  1. Argument 1 ist, dass es eine Fehlerquelle beseitigt, wenn Leute von Klassen erben und dann besseren Zugriff auf die Interna dieser Klasse haben, ohne die Interna wirklich richtig zu verstehen.

  2. Argument 2 ist, dass, wenn Sie eine Microsoft-Klasse erweitern und dann Microsoft eine Fehlerbehebung in dieser Klasse implementieren, Ihre Erweiterung sich jedoch auf diesen Fehler stützt, Ihr Code jetzt kaputt ist, Microsoft die Schuld erhält und dies verhindert

  3. Argument 3 ist, dass ich als Entwickler der Klasse die Wahl habe, sie im Rahmen meines Entwurfs der Klasse zu erweitern.

Argument 1 scheint ein Argument zu sein, dass Sie als Endprogrammierer nicht wissen, wie man meinen Code verwendet. Das mag der Fall sein, aber wenn Sie mir weiterhin erlauben, auf die Objektschnittstelle zuzugreifen, gilt immer noch, dass ich Ihr Objekt verwende und es aufrufe, ohne zu verstehen, wie es zu verwenden ist, und auf diese Weise genauso viel Schaden anrichten kann . Dies ist eine schwache Rechtfertigung für die Notwendigkeit der Versiegelung.

Ich verstehe, woher die sachliche Grundlage für arg 2 stammt. Insbesondere, wenn Microsoft Win32-API-Aufrufe durch zusätzliche Betriebssystemprüfungen überprüft, um fehlerhafte Aufrufe zu identifizieren, die die allgemeine Stabilität von Windows XP im Vergleich zu Windows NT verbessert haben, aber kurzfristig dazu geführt haben, dass viele Apps bei der Veröffentlichung von Windows XP beschädigt wurden. Microsoft hat dies behoben, indem "Regeln" für diese Überprüfungen eingefügt wurden, um zu sagen, dass es ein bekannter Fehler ist, wenn App X diese Regel verletzt

Argument 2 ist ein schlechtes Argument, da Sealed im besten Fall keinen Unterschied dazu macht, denn wenn es einen Fehler in der .NET-Bibliothek gibt, haben Sie keine andere Wahl, als eine Lösung zu finden, und wenn die Microsoft-Korrektur herauskommt, ist dies sehr wahrscheinlich bedeutet, dass Ihre Arbeit, die vom fehlerhaften Verhalten abhängt, jetzt fehlerhaft ist. Unabhängig davon, ob Sie dies mithilfe der Vererbung oder eines anderen zusätzlichen Wrapper-Codes umgangen haben, wird Ihre Arbeit unterbrochen, wenn der Code behoben ist.

Argument 3 ist das einzige Argument, das irgendeine Substanz hat, um sich selbst zu rechtfertigen. Aber es ist immer noch schwach. Das widerspricht einfach der Wiederverwendung von Code.


2
/ me sendet eine E-Mail an Microsoft. Können Sie die Klasse X für mich entsiegeln und eine neue Version von .NET herausgeben? Mit freundlichen Grüßen, .... Wie gesagt, das einzige Mal in der kommerziellen Entwicklung, dass ich eine versiegelte Klasse gesehen habe, war es nicht möglich, sie zu entsiegeln.
Michael Shaw

6
It is impossible to write a class thinking about every possible way it could be used- Das ist genau der Grund, warum viele Framework-Klassen versiegelt sind ... Es muss nicht mehr überlegt werden, wie jemand die Klasse erweitern könnte.
Robert Harvey

5
Wenn Sie es entsiegeln könnten, hätte es nicht viel Sinn, es zu versiegeln, oder?
Robert Harvey

2
@Ptolemy Es ist eine Funktion, den Leuten zu erlauben, Ihre Klasse zu erweitern . Eine, die einen erheblichen Entwicklungsaufwand verursacht. Es lohnt sich nur zu rechtfertigen, wenn der Autor der Klasse in potenziellen Erweiterungen genügend Nutzen sieht, um den Aufwand zu rechtfertigen. Wenn sie den Aufwand nicht rechtfertigen können und der Typ und seine Benutzer die Erweiterung nicht unterstützen, ist es wichtig, dies zu verhindern. Andernfalls können Sie den Typ technisch erweitern, es ist jedoch unwahrscheinlich, dass er ordnungsgemäß funktioniert, wenn du tust das
Servy

2
@ Kawas: Sie sind nur schwierig.
Robert Harvey


-8

Wie meine Frage zeigt, bin ich hier kein Experte. Aber ich sehe keinen Grund sealed, überhaupt zu existieren.

Es scheint gemacht zu sein, um Code-Architekten beim Entwerfen einer Schnittstelle zu helfen. Wenn Sie eine Klasse schreiben möchten, die in der Wildnis veröffentlicht wird und von der viele Menschen erben, kann das Ändern von Elementen in dieser Klasse zu einer Unterbrechung für zu viele Menschen führen. So können wir es versiegeln und niemand kann erben. "Problem gelöst".

Sieht so aus, als würde man "eine Stelle abdecken und eine andere aufdecken". Und es löst nicht einmal ein Problem - es beseitigt nur ein Werkzeug : die Vererbung. Wie jedes Tool hat es viele Verwendungen und das Erben von einer instabilen Klasse ist ein Risiko, das Sie eingehen. Wer dieses Risiko eingeht, sollte es besser wissen.

Vielleicht könnte es ein Schlüsselwort geben stable, damit die Leute wissen, dass es sicherer ist, davon zu erben.


2
"Problem gelöst" - Genau.
Robert Harvey

@RobertHarvey Es ist nicht gelöst, wie im nächsten Abschnitt erläutert.
Cregox

8
Du bist nur sauer, weil du die Klasse nicht erweitern kannst. Das bedeutet nicht, dass dies sealedkein nützliches Werkzeug für die Framework-Designer ist. Klassen in einem Framework sollten Black Boxes sein. Sie sollten nicht über die Interna einer Klasse Bescheid wissen müssen, um sie richtig verwenden zu können. Doch genau das verlangt die Vererbung.
Robert Harvey

Ich habe nie gesagt, dass es nicht nützlich ist. Ich sage, ich sehe seine Verwendung nicht und weise darauf hin, warum. Bitte, ich flehe dich an, gib mir einen guten Grund, es zu benutzen! Auch wenn es nur "weil ich einem geschlossenen Designmuster folgen will" ist das in Ordnung. Ich sehe niemanden, der diesen Grund ausdrücklich angibt.
Cregox

7
Der gute Grund ist, dass Sie die Vererbung für eine versiegelte Klasse nicht unterstützen müssen.
Robert Harvey
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.