Was ist der Unterschied zwischen den beiden folgenden UpdateSubject-Methoden? Ich fand es besser, statische Methoden zu verwenden, wenn Sie nur mit den Entitäten arbeiten möchten. In welchen Situationen sollte ich nicht statische Methoden anwenden?
public class Subject
{
public int Id {get; set;}
public string Name { get; set; }
public static bool UpdateSubject(Subject subject)
{
//Do something and return result
return true;
}
public bool UpdateSubject()
{
//Do something on 'this' and return result
return true;
}
}
Ich weiß, dass ich für diese wirklich nervige Frage viele Kicks von der Community bekommen werde, aber ich konnte mich nicht davon abhalten, sie zu stellen.
Wird dies beim Umgang mit Vererbung unpraktisch?
Update:
Es passiert jetzt bei uns am Arbeitsplatz. Wir arbeiten an einer 6-monatigen asp.net-Webanwendung mit 5 Entwicklern. Unser Architekt entschied, dass wir alle statischen Methoden für alle APIs verwenden. Seine Argumente für statische Methoden sind geringes Gewicht und es kommt Webanwendungen zugute, indem die Serverlast niedrig gehalten wird.
quelle
Antworten:
Ich gehe mit den offensichtlichsten Problemen statischer Methoden mit expliziten "this" -Parametern um:
Sie verlieren den virtuellen Versand und anschließend den Polymorphismus. Sie können diese Methode in einer abgeleiteten Klasse niemals überschreiben. Natürlich können Sie eine
new
(static
) -Methode in einer abgeleiteten Klasse deklarieren , aber jeder Code, der darauf zugreift, muss die gesamte Klassenhierarchie kennen und explizite Überprüfungen und Umwandlungen durchführen, was genau das ist, was OO vermeiden soll .Bei einer Erweiterung von 1 können Sie Instanzen der Klasse nicht durch ein Interface ersetzen , da Interfaces (in den meisten Sprachen) keine
static
Methoden deklarieren können.Die unnötige Ausführlichkeit. Was ist besser lesbar:
Subject.Update(subject)
oder einfachsubject.Update()
?Argumentüberprüfung. Auch dies hängt von der Sprache ab, aber viele kompilieren eine implizite Prüfung, um sicherzustellen, dass das
this
Argument nicht dazu dientnull
, zu verhindern, dass ein Nullreferenzfehler unsichere Laufzeitbedingungen erzeugt (Art eines Pufferüberlaufs). Wenn Sie keine Instanzmethoden verwenden, müssen Sie diese Prüfung am Anfang jeder Methode explizit hinzufügen.Es ist verwirrend. Wenn ein normaler, vernünftiger Programmierer eine
static
Methode sieht , geht er natürlich davon aus, dass keine gültige Instanz erforderlich ist (es sei denn, es werden mehrere Instanzen wie eine Vergleichs- oder Gleichheitsmethode benötigt oder es wird erwartet, dass sienull
Referenzen verarbeiten können). . Wenn wir sehen, wie statische Methoden auf diese Weise angewendet werden, müssen wir eine doppelte oder dreifache Aufnahme machen, und nach dem vierten oder fünften Mal werden wir gestresst und wütend sein und Gott helfe Ihnen, wenn wir Ihre Privatadresse kennen.Es ist eine Form der Vervielfältigung. Was beim Aufrufen einer Instanzmethode tatsächlich passiert, ist, dass der Compiler oder die Laufzeit die Methode in der Methodentabelle des Typs nachschlägt und sie
this
als Argument aufruft . Grundsätzlich implementieren Sie neu, was der Compiler bereits tut. Sie verletzen DRY und wiederholen denselben Parameter in verschiedenen Methoden immer wieder, wenn er nicht benötigt wird.Es ist schwer, sich einen guten Grund vorzustellen, Instanzmethoden durch statische Methoden zu ersetzen. Bitte nicht
quelle
File
,FileInfo
undDirectoryInfo
(und in der Tat gibt es Bibliotheken , die sie hinter Schnittstellen verstecken , die dann je nach Bedarf und in Tests verspottet aus injiziert werden können).Sie haben ziemlich genau beschrieben, wie Sie OOP in C ausführen, in dem nur statische Methoden verfügbar sind, und "this" ist ein Strukturzeiger. Und ja, Sie können Laufzeitpolymorphie in C ausführen, indem Sie während der Konstruktion einen Funktionszeiger angeben, der als ein Element der Struktur gespeichert werden soll. In anderen Sprachen verfügbare Instanzmethoden sind nur syntaktischer Zucker, der im Grunde genau dasselbe unter der Haube tut. Einige Sprachen, wie z. B. Python, befinden sich auf halber Strecke, wobei der "self" -Parameter explizit aufgeführt ist. Eine spezielle Syntax für den Aufruf übernimmt jedoch die Vererbung und den Polymorphismus für Sie.
quelle
obj->type->mthd(obj, ...);
und das ist im Wesentlichen ähnlich wie beim virtuellen Versand in anderen Sprachen (aber hinter den Kulissen).Das Problem mit der statischen Methode tritt in dem Moment auf, in dem Sie eine Unterklasse benötigen.
Statische Methoden können in Unterklassen nicht überschrieben werden. Daher können Ihre neuen Klassen keine neuen Implementierungen der Methoden bereitstellen, sodass sie weniger nützlich sind.
quelle
Wenn Sie eine Methode deklarieren
static
, müssen Sie kein Objekt aus der Klasse instanziieren (mithilfe desnew
Schlüsselworts), um die Methode auszuführen. Sie können jedoch nur dann auf Elementvariablen verweisen, wenn diese ebenfalls statisch sind. In diesem Fall gehören diese Elementvariablen zur Klasse und nicht zu einem bestimmten instanziierten Objekt der Klasse.Anders ausgedrückt, das
static
Schlüsselwort bewirkt , dass eine Deklaration Teil der Klassendefinition ist, sodass sie für alle Instanzen der Klasse (aus der Klasse instanziierte Objekte) zu einem einzigen Referenzpunkt wird .Wenn Sie also mehrere laufende Kopien Ihrer Klasse möchten und nicht möchten, dass der Status (Elementvariablen) von allen laufenden Kopien gemeinsam genutzt wird (dh, jedes Objekt hat seinen eigenen Status), dann Sie Diese Mitgliedsvariablen können nicht als statisch deklariert werden.
Im Allgemeinen sollten Sie
static
Klassen und Methoden nur verwenden, wenn Sie Dienstprogrammmethoden erstellen, die einen oder mehrere Parameter akzeptieren und ein Objekt zurückgeben, ohne dass Nebenwirkungen auftreten (dh Änderungen an Statusvariablen in der Klasse).quelle
static
bedeutet, fragt er, warum nicht einfach alles als statisch deklariert werden soll.Subject
- aber als expliziter Parameter anstelle des implizitenthis
Parameter.this
Parameter. Es gibt Unterschiede in den Erwartungen, aber außerhalb von inheritence, gibt es keinen wirklichen Unterschied in dem, was Sie können tun. Auf diese nicht statischen Elemente kann beispielsweise über den Parameter explicit zugegriffen werden.Der Grund, warum Leute argumentieren, dass "statische Methoden schlechtes Design zeigen", liegt nicht unbedingt an den Methoden, sondern an statischen Daten, implizit oder explizit. Implizit meine ich JEDEN Zustand im Programm, der nicht in den Rückgabewerten oder Parametern enthalten ist. Das Ändern des Zustands in einer statischen Funktion ist ein Rückfall in die prozedurale Programmierung. Wenn die Funktion den Status jedoch nicht ändert oder die Statusänderung an Komponentenobjektfunktionen delegiert, handelt es sich eher um ein Funktionsparadigma als um eine Prozedur.
Wenn Sie den Status nicht ändern, können statische Methoden und Klassen viele Vorteile haben. Dies erleichtert die Sicherstellung der Reinheit einer Methode und ist somit nebenwirkungsfrei und fehlerfrei und vollständig reproduzierbar. Es stellt außerdem sicher, dass unterschiedliche Methoden in mehreren Anwendungen, die eine gemeinsam genutzte Bibliothek verwenden, bei gleicher Eingabe dieselben Ergebnisse erzielen, was sowohl die Fehlerverfolgung als auch das Testen von Einheiten erheblich vereinfacht.
Letztendlich gibt es in der Praxis keinen Unterschied zwischen übergroßen Objekten wie StateManager und statischen oder globalen Daten. Der Vorteil von statischen Methoden ist, dass sie auf die Absicht des Autors hinweisen, den Status nicht für spätere Bearbeiter zu ändern.
quelle
making ... unit testing much easier.
Nein, wird es nicht. Es macht es keinen Code macht , die statischen Methoden unmöglich nennt Einheit Test, da Sie es nicht aus der statischen Methode isolieren können. Ein Aufruf einer statischen Methode wird zu einer fest codierten Abhängigkeit von dieser Klasse.Abhängig von der Sprache und dem, was Sie versuchen, kann die Antwort sein, dass es nicht viel Unterschied gibt, aber die
static
Version hat ein bisschen mehr Unordnung.Da Ihre Beispielsyntax Java oder C # vorschlägt, halte ich Thorbjørn Ravn Andersen für richtig, um auf das vorrangige Problem (mit später Bindung) hinzuweisen. Bei einer statischen Methode gibt es keinen "speziellen" Parameter für die späte Bindung, sodass Sie keine späte Bindung haben können.
Tatsächlich ist eine statische Methode nur eine Funktion in einem Modul, das denselben Namen wie die Klasse hat - es ist überhaupt keine OOP-Methode.
quelle
Du besiegst im Grunde den ganzen Punkt von Objekten, wenn du dies tust. Es gibt einen guten Grund, warum wir vom prozeduralen Code zum objektorientierten Code übergegangen sind.
Ich würde NIEMALS eine statische Methode deklarieren, die den Klassentyp als Parameter verwendet. Das macht den Code einfach komplexer, ohne Gewinn.
quelle
object
an einestatic
Methode übergeben und eine neue zurückgebenobject
. Funktionale Programmierer tun dies die ganze Zeit.Math
statische klasse "complex for no gain" an oder würdest du es vorziehen, wenn alle zahlentypen virtuelle methoden hätten, die absoluten wert, negation, addition, quadrierung, beliebige wurzeln und so weiter definieren? Ich glaube nicht Objekte sind ordentlich, wenn Sie versteckte veränderbare Zustände speichern müssen, in denen Sie einige Invarianten erzwingen müssen. JEDE erdenkliche Methode, die auf einen Typ angewendet wird, in den Typ selbst zusammenzufassen, ist etwas, das zu komplexem und nicht wartbarem Code führt. Ich stimme Robert zu, vielleicht möchten Sie sich ansehen, wie funktionierende Programmierer arbeiten, es kann ein echter Augenöffner sein!Hier gibt es viele großartige Antworten, und sie sind viel aufschlussreicher und sachkundiger als alles, was ich jemals als Antwort finden könnte.
"Unser Architekt entschied, dass wir alle statischen Methoden für alle APIs verwenden. Seine Argumentation als statische Methoden ist leicht und es kommt Webanwendungen zugute, indem die Serverlast niedrig gehalten wird ."
(kühne Betonung liegt bei mir)
Mein 2c zu diesem Teil der Frage lautet:
Theoretisch ist das, was dort gesagt wird, wahr: Der Aufruf einer statischen Methode hat nur den Overhead, diese Methode tatsächlich aufzurufen. Das Aufrufen einer nicht statischen (Instanz-) Methode hat den zusätzlichen Aufwand, das Objekt zuerst zu instanziieren und zu einem bestimmten Zeitpunkt die Instanz zu zerstören (entweder manuell oder über irgendeine Form der automatischen Speicherbereinigung, abhängig von der verwendeten Plattform).
Das Spiel ein wenig von Devils Befürworter dazu: Wir können noch weiter gehen und Sachen sagen wie:
Dies kann sehr schlimm werden, wenn für jeden Aufruf der (Instanz-) Methode eine Instanz erstellt wird (anstatt sie einfach statisch zu lassen und so aufzurufen).
Abhängig von der Komplexität des Konstruktors, der Typhyerarchie, anderen Instanzmitgliedern und anderen solchen unbekannten Faktoren kann der zusätzliche Overhead des nicht statischen Methodenaufrufs variieren und sehr groß werden
In Wahrheit, IMHO, sind die obigen Punkte (und der allgemeine Ansatz von "Verwenden wir Statik, weil sie schneller ist") Strohmann-Argumente / Einschätzungen:
Wenn der Code gut ist und speziell für dieses Argument, wenn die Instanzen nur bei Bedarf erstellt (und in optimaler Weise zerstört) werden, entsteht kein zusätzlicher Aufwand durch die Verwendung von Insance-Methoden, wenn dies angezeigt ist (wenn Sie dies möchten) erstelle nur die benötigten Objekte, diese wären auch dann erstellt worden, wenn diese Methode als statisch deklariert worden wäre.
Wenn Sie die statische Methodendeklaration auf diese Weise missbrauchen, können Sie einige Probleme mit Ihrem Code in Bezug auf die Erstellung von Instanzen verbergen.
quelle
Dies ist eine sehr interessante Frage, die in der Regel sehr unterschiedliche Antworten hat, je nachdem, welche Community Sie sie stellen. Andere Antworten scheinen C # oder Java Bias zu sein: eine Programmiersprache, die (meistens) objektorientiert ist und eine Art idiomatische Sicht auf die Objektorientierung hat.
In anderen Communities wie C ++ wird die Objektorientierung freier interpretiert. Einige bekannte Experten haben sich mit dem Thema befasst und kommen zu dem Schluss, dass freie Funktionen die Kapselung verbessern (der Schwerpunkt liegt bei mir):
Für diejenigen, die mit der C ++ - Terminologie nicht vertraut sind:
Um Ihre Frage zu beantworten:
Nein, Sie sollten nicht immer statische Methoden verwenden.
Sie sollten sie jedoch immer dann verwenden, wenn Sie nur die öffentliche API einer Klasse verwenden müssen.
quelle
in Java ...
Statische Methoden werden nicht überschrieben, sondern ausgeblendet. Dies wäre ein großer Unterschied (Problem?) Bei der Erweiterung der Klasse.
Andererseits ist mir aufgefallen, dass Java-Programmierer die Tendenz haben zu denken, alles MUSS objektiv sein, ohne wirklich zu verstehen, warum, und ich bin anderer Meinung.
Statisch sollte für den Code verwendet werden, der für die Klasse spezifisch ist. Statisch funktioniert nicht gut mit Vererbung.
Einige gute Beispiele für die Verwendung statischer Methoden sind eigenständige Funktionen ohne Nebenwirkungen.
siehe auch das Stichwort synchronisiert ...
quelle