In Java können Sie die Methode als endgültig markieren, um ein Überschreiben zu verhindern.
In C # müssen Sie die Methode als virtuell markieren , es zu machen möglich außer Kraft zu setzen.
Bedeutet dies, dass Sie in C # alle Methoden als virtuell markieren sollten (mit Ausnahme einiger Methoden, die nicht überschrieben werden sollen), da Sie höchstwahrscheinlich nicht wissen, auf welche Weise Ihre Klasse vererbt werden kann?
c#
java
methods
virtual-functions
Georgii Oleinikov
quelle
quelle
final
Felder, ich weiß, dass er über sie spricht. Aber ich denke , dass er auch über endgültige Methoden in spricht Effective Java . Ich kann mich jedoch falsch daran erinnern. Ich bin mir aber sicher, dass er es damals woanders erwähnt hat - vielleicht in einem seiner Gespräche.Antworten:
Nein. Wenn die Sprachdesigner der Meinung wären , dass virtuell die Standardeinstellung sein sollte , wäre dies die Standardeinstellung gewesen .
Überschreibbarkeit ist eine Funktion , die wie alle Funktionen Kosten verursacht . Die Kosten einer überschreibbaren Methode sind beträchtlich: Es entstehen hohe Kosten für Design, Implementierung und Test, insbesondere wenn die Klasse "empfindlich" ist. Virtuelle Methoden sind Möglichkeiten, nicht getesteten Code von Drittanbietern in ein System einzuführen, was sich auf die Sicherheit auswirkt.
Wenn Sie nicht wissen, wie Ihre Klasse vererbt werden soll , veröffentlichen Sie Ihre Klasse nicht, da Sie das Entwerfen noch nicht abgeschlossen haben. Ihr Erweiterbarkeitsmodell sollten Sie unbedingt im Voraus kennen. Dies sollte Ihre Entwurfs- und Teststrategie stark beeinflussen.
Ich befürworte, dass alle Klassen versiegelt und alle Methoden nicht virtuell sind, bis Sie einen realen, kundenorientierten Grund haben, eine Methode zu entsiegeln oder virtuell zu machen.
Grundsätzlich lautet Ihre Frage: "Ich weiß nicht, wie meine Kunden meine Klasse konsumieren möchten. Sollte ich sie daher willkürlich erweiterbar machen?" Nein; Sie sollten sich auskennen ! Sie würden nicht fragen: "Ich weiß nicht, wie meine Kunden meine Klasse verwenden werden. Soll ich also alle meine Eigenschaften schreibgeschützt machen? Und sollte ich alle meine Methoden schreibgeschützt vom Delegatentyp machen, damit meine Benutzer." kann jede Methode durch eine eigene Implementierung ersetzen? " Nein, tun Sie nichts davon, bis Sie Beweise dafür haben , dass ein Benutzer diese Fähigkeit tatsächlich benötigt! Verbringen Sie Ihre wertvolle Zeit damit, Funktionen zu entwerfen, zu testen und zu implementieren, die Benutzer tatsächlich wollen und brauchen, und zwar aus einer Position des Wissens heraus.
quelle
sealed
standardmäßig sein sollten, was sie nicht sind.Meiner Meinung nach ist die derzeit akzeptierte Antwort unnötig dogmatisch.
Fakt ist, wenn Sie eine Methode nicht als markieren
virtual
, können andere ihr Verhalten nicht überschreiben, und wenn Sie eine Klasse als markieren,sealed
können andere nicht von der Klasse erben. Dies kann erhebliche Schmerzen verursachen. Ich weiß nicht, wie oft ich eine API zum Markieren von Klassensealed
oder zum Nichtmarkieren von Methoden verflucht habe ,virtual
nur weil sie meinen Anwendungsfall nicht vorweggenommen haben.Theoretisch mag es der richtige Ansatz sein, nur überschreibende Methoden und das Erben von Klassen zuzulassen, die überschrieben und vererbt werden sollen. In der Praxis ist es jedoch unmöglich, jedes mögliche Szenario vorherzusehen, und es gibt wirklich keinen guten Grund, sich so zu verschließen.
sealed
.virtual
.Eine Möglichkeit, den Aufruf zu tätigen, besteht darin, den Namen der Methode oder Eigenschaft zu überprüfen. Eine GetLength () -Methode in einer Liste macht genau das, was der Name impliziert, und lässt nicht viel Interpretation zu . Eine Änderung der Implementierung wäre wahrscheinlich nicht sehr transparent, so dass es
virtual
wahrscheinlich unnötig ist , sie zu markieren . Das Markieren derAdd
Methode als virtuell ist weitaus nützlicher, da jemand eine spezielle Liste erstellen könnte, die nur einige Objekte über die Add-Methode usw. akzeptiert. Ein weiteres Beispiel sind benutzerdefinierte Steuerelemente. Sie möchten die Hauptzeichnungsmethode festlegen,virtual
damit andere den Großteil des Verhaltens verwenden und nur das Aussehen ändern können, aber Sie würden die X- und Y-Eigenschaften wahrscheinlich nicht überschreiben.Am Ende muss man diese Entscheidung oft nicht sofort treffen. In einem internen Projekt, in dem Sie den Code trotzdem leicht ändern können, würde ich mir über diese Dinge keine Sorgen machen. Wenn eine Methode überschrieben werden muss, können Sie sie in diesem Fall jederzeit virtuell gestalten. Im Gegenteil, wenn das Projekt eine API oder Bibliothek ist, die von anderen verwendet wird und nur langsam aktualisiert wird, lohnt es sich auf jeden Fall, darüber nachzudenken, welche Klassen und Methoden nützlich sein könnten. In diesem Fall denke ich, dass es besser ist, offen zu sein, als streng geschlossen zu sein.
quelle
Nein! Da Sie nicht wissen, wie Ihre Klasse vererbt wird, sollten Sie eine Methode nur so markieren, als
virtual
ob Sie wissen , dass sie überschrieben werden soll.quelle
Nein. Nur Methoden, die abgeleitete Klassen angeben sollen, sollten virtuell sein.
Virtual ist nicht mit final verbunden.
Um zu verhindern, dass eine virtuelle Methode in c # überschrieben wird, verwenden Sie
sealed
public class MyClass { public sealed override void MyFinalMethod() {...} }
quelle
final
auf eine Methode bedeutetnot virtual
.Wir können Gründe für / wieder beide Lager heraufbeschwören, aber das ist völlig nutzlos.
In Java gibt es Millionen unbeabsichtigter nicht endgültiger öffentlicher Methoden, aber wir hören nur sehr wenige Horrorgeschichten.
In C # gibt es Millionen versiegelter öffentlicher Methoden, und wir hören nur sehr wenige Horrorgeschichten.
Es ist also keine große Sache - die Notwendigkeit, eine öffentliche Methode außer Kraft zu setzen, ist selten, daher ist sie in beiden Fällen umstritten.
Dies erinnert mich an ein anderes Argument - ob eine lokale Variable standardmäßig endgültig sein soll. Es ist eine ziemlich gute Idee, aber wir können nicht übertreiben, wie wertvoll sie ist. Es gibt Milliarden lokaler Variablen, die endgültig sein könnten, aber nicht endgültig sind, aber es hat sich gezeigt, dass es sich um ein tatsächliches Problem handelt.
quelle
Wenn Sie eine Methode virtuell machen, wird im Allgemeinen jeder Code verlangsamt, der sie aufrufen muss. Diese Verlangsamung ist unbedeutend, kann jedoch in einigen Fällen recht groß sein (unter anderem, weil nicht virtuelle Methodenaufrufe inline sein können, wodurch der Optimierer möglicherweise unnötige Vorgänge eliminieren kann). Es ist nicht immer möglich vorherzusagen, inwieweit virtuelle Aufrufe die Ausführungsgeschwindigkeit beeinflussen können, und es sollte generell ungültig sein, Dinge zu tun, die den Code langsamer machen, es sei denn, es gibt einen erkennbaren Vorteil dafür.
Der Leistungsvorteil, Methoden nicht virtuell zu machen, reicht wahrscheinlich in vielen Fällen aus, um zu rechtfertigen, dass Methoden standardmäßig nicht virtuell sind. Wenn Klassen jedoch so konzipiert sind, dass sie vererbt werden, sollten die meisten Methoden virtuell und nicht versiegelt sein. Die primäre Verwendung für nicht virtuelle oder versiegelte Methoden sollte als Wrapper für andere (möglicherweise geschützte) virtuelle Methoden erfolgen (Code, der das zugrunde liegende Verhalten ändern möchte, sollte den entsprechenden virtuellen und nicht den Wrapper überschreiben).
Es gibt häufig nicht leistungsbezogene Gründe für das Markieren von Klassen als
sealed
oder das Beschränken der Vererbung auf andere Klassen innerhalb der Assembly. Wenn eine Klasse extern vererbbar ist, werden unter anderem alle Mitglieder mitprotected
Gültigkeitsbereich effektiv zu ihrer öffentlichen API hinzugefügt, und Änderungen an ihrem Verhalten in der Basisklasse können abgeleitete Klassen beschädigen, die auf diesem Verhalten beruhen. Wenn andererseits eine Klasse vererbbar ist,virtual
erhöht das Erstellen ihrer Methoden ihre Exposition nicht wirklich. Wenn überhaupt, kann dies die Abhängigkeit der abgeleiteten Klasse von den Interna der Basisklasse verringern, indem sie ihnen ermöglicht, Aspekte der Implementierung der Basisklasse, die in der abgeleiteten Klasse nicht mehr relevant sind, vollständig zu "begraben" [z. B. wenn die Mitglieder vonList<T>
waren virtuell, eine abgeleitete Klasse, die sie alle überschrieb, konnte ein Array von Arrays verwenden, um Dinge zu speichern (um Probleme mit großen Objekthaufen zu vermeiden), und musste nicht versuchen, das verwendete private ArrayList<T>
konsistent mit dem Array von zu halten Arrays.quelle
Ja du solltest. Ich möchte eine andere Antwort als die meisten anderen Antworten beantworten. Dies ist ein Fehler in C #. Ein Defekt. Ein Fehler im Design. Sie können dies beim Vergleich mit Java sehen, wo alle Methoden "virtuell" sind, sofern nicht anders angegeben ("final"). Natürlich, wenn es eine Klasse "Rechteck" mit der Methode "Fläche" gibt und Sie eine eigene Klasse haben möchten, die ein "Rechteck" mit Rändern darstellt. Sie möchten die vorhandene Klasse mit all ihren Eigenschaften und Methoden nutzen und nur eine Eigenschaft mit dem Rand "margin" hinzufügen, die dem regulären Rechteckbereich einen gewissen Wert hinzufügt. Wenn die Bereichsmethode in Rectangle nicht als virtuell markiert ist, du bist verdammt. Bild bitte eine Methode, die ein Array von Rechtecken nimmt und die Summe der Fläche aller Rechtecke zurückgibt. Einige können regelmäßige Rechtecke sein, andere mit Rand. Lesen Sie nun die Antwort zurück, die als "korrekt" gekennzeichnet ist, und beschreiben Sie "Sicherheitsproblem" oder "Testen". Diese sind im Vergleich zur Übersteuerungsbehinderung bedeutungslos.
Ich bin nicht überrascht, dass andere mit "Nein" geantwortet haben. Ich bin überrascht, dass die Autoren von C # das nicht sehen konnten, als sie ihre Sprache auf Java basierten.
quelle
Nein, Sie sollten nicht alle Methoden als virtuell markieren. Sie sollten überlegen, wie Ihre Klasse vererbt werden könnte. Wenn die Klasse nicht vererbt werden soll, markieren Sie sie versiegelt und die Mitglieder sollten offensichtlich nicht virtuell sein. Wenn Ihre Klasse wahrscheinlich vererbt wird, sollten Sie die Fähigkeit maximieren, das Verhalten zu überschreiben. Verwenden Sie daher in solchen Klassen großzügig überall virtuell, es sei denn, Sie haben einen Grund, dies nicht zu tun.
quelle