it-swarm.dev

Kann ich nicht einfach alle statischen Methoden verwenden?

Was ist der Unterschied zwischen den beiden folgenden UpdateSubject-Methoden? Ich fand, dass die Verwendung statischer Methoden besser ist, wenn Sie nur die Entitäten bearbeiten möchten. In welchen Situationen sollte ich mit nicht statischen Methoden arbeiten?

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 Tritte von der Community bekommen werde, aber ich konnte mich nicht davon abhalten, sie zu stellen.

Wird dies beim Umgang mit Vererbung unpraktisch?

Aktualisieren:
Es passiert jetzt an unserem Arbeitsplatz. Wir arbeiten an einer 6-monatigen asp.net-Webanwendung mit 5 Entwicklern. Unser Architekt hat entschieden, dass wir alle statischen Methoden für alle APIs verwenden. Seine Argumentation, statische Methoden zu sein, ist gering und es kommt Webanwendungen zugute, indem es die Serverlast niedrig hält.

65
Alexander

Ich werde auf die offensichtlichsten Probleme statischer Methoden mit expliziten "this" -Parametern eingehen:

  1. 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 Castings durchführen genau das, was OO soll vermeiden.

  2. Als eine Art Erweiterung von # 1 können Sie Instanzen der Klasse nicht durch eine Schnittstelle ersetzen, da Schnittstellen (in den meisten Sprachen) nicht deklarieren können static Methoden.

  3. Die unnötige Ausführlichkeit. Was ist besser lesbar: Subject.Update(subject) oder nur subject.Update()?

  4. Argumentprüfung. Dies hängt wiederum von der Sprache ab, aber viele kompilieren eine implizite Prüfung, um sicherzustellen, dass das Argument this nicht null ist, um zu verhindern, dass ein Nullreferenzfehler unsichere Laufzeitbedingungen (eine Art Puffer) erzeugt überlaufen). Wenn Sie keine Instanzmethoden verwenden, müssen Sie diese Prüfung explizit am Anfang jeder Methode hinzufügen.

  5. Es ist verwirrend. Wenn ein normaler, vernünftiger Programmierer eine static -Methode sieht, wird er natürlich annehmen, dass dies nicht der Fall ist 't erfordern eine gültige Instanz (es sei denn, es werden mehrere Instanzen wie eine Vergleichs- oder Gleichheitsmethode benötigt oder es wird erwartet, dass sie mit null Referenzen arbeiten können). Wenn wir sehen, wie statische Methoden auf diese Weise angewendet werden, werden wir eine doppelte oder vielleicht dreifache Aufnahme machen, und nach dem 4. oder 5. Mal werden wir gestresst und wütend sein und Gott helfe Ihnen, wenn wir Ihre Privatadresse kennen.

  6. 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 mit this als Argument aufruft. Sie implementieren im Grunde genommen neu, was der Compiler bereits tut. Sie verletzen DRY und wiederholen denselben Parameter immer wieder auf verschiedene Arten, wenn er nicht benötigt wird.

Es ist schwer, sich einen gut Grund vorzustellen, Instanzmethoden durch statische Methoden zu ersetzen. Bitte nicht.

87
Aaronaught

Sie haben ziemlich genau beschrieben, wie Sie OOP in C, in dem nur statische Methoden verfügbar sind, und "this" ist ein Strukturzeiger. Und ja, Sie können Laufzeitpolymorphismus in ausführen C durch Angabe eines Funktionszeigers während der Konstruktion, der als ein Element der Struktur gespeichert werden soll. In anderen Sprachen verfügbare Instanzmethoden sind nur syntaktischer Zucker, der im Wesentlichen genau dasselbe unter der Haube tut. Einige Sprachen, wie Python, befinden sich auf halbem Weg zwischen wo Der Parameter "self" wird explizit aufgelistet, aber eine spezielle Syntax für den Aufruf behandelt die Vererbung und den Polymorphismus für Sie.

13
Karl Bielefeldt

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, wodurch sie weniger nützlich sind.

10
user1249

Wenn Sie eine Methode static deklarieren, müssen Sie kein Objekt aus der Klasse instanziieren (mit dem Schlüsselwort new), um die Methode auszuführen. Sie können jedoch nicht auf Mitgliedsvariablen verweisen es sei denn, sie sind auch statisch In diesem Fall sind diese Mitgliedsvariablen gehören zur Klasse kein bestimmtes instanziiertes Objekt der Klasse .

Anders ausgedrückt, das Schlüsselwort static bewirkt, dass eine Deklaration Teil der Klassendefinition ist, sodass sie zu einem einzelnen Referenzpunkt über alle Instanzen der Klasse (aus der Klasse instanziierte Objekte) wird. .

Daraus folgt, dass Sie, wenn Sie mehrere laufende Kopien Ihrer Klasse möchten und nicht möchten, dass der Status (Mitgliedsvariablen) von allen Ihren laufenden Kopien gemeinsam genutzt wird (dh jedes Objekt hat seinen eigenen eindeutigen Status) 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 Nebenwirkungen (dh Änderungen an Zustandsvariablen in der Klasse)

7
Robert Harvey

Der Grund, warum Leute argumentieren, dass "statische Methoden schlechtes Design zeigen", liegt nicht unbedingt an den Methoden, sondern an impliziten oder expliziten statischen Daten. Mit implizit meine ich JEDEN Status im Programm, der nicht in den Rückgabewerten oder Parametern enthalten ist. Das Ändern des Status in einer statischen Funktion ist ein Rückschritt zur prozeduralen Programmierung. Wenn die Funktion jedoch den Status nicht ändert oder die Statusänderung an Komponentenobjektfunktionen delegiert, ist dies eher ein Funktionsparadigma als ein prozedurales.

Wenn Sie den Status nicht ändern, können statische Methoden und Klassen viele Vorteile haben. Es macht es viel einfacher sicherzustellen, dass eine Methode rein und somit frei von Nebenwirkungen ist und Fehler vollständig reproduzierbar sind. Außerdem wird sichergestellt, dass verschiedene Methoden in mehreren Anwendungen, die eine gemeinsam genutzte Bibliothek verwenden, sichergestellt werden können, dass sie bei derselben 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 der korrekt verwendeten statischen Methoden besteht darin, dass sie die Absicht des Autors anzeigen können, den Status nicht für spätere Revisoren zu ändern.

3
Mathieson

Dies ist eine sehr interessante Frage, die je nach Community, die Sie stellen, sehr unterschiedliche Antworten hat. Andere Antworten scheinen C # oder Java Bias: eine Programmiersprache zu sein, die (meistens) rein objektorientiert ist und eine Art idiomatische Sicht auf die Objektorientierung hat.

In anderen Communities wie C++ wird die Objektorientierung liberaler interpretiert. Einige bekannte Experten haben sich mit dem Thema befasst und kommen zu dem Schluss, dass freie Funktionen verbessern die Kapselung (Schwerpunkt liegt bei mir):

Wir haben jetzt gesehen, dass ein vernünftiger Weg, um den Umfang der Kapselung in einer Klasse zu messen, darin besteht, die Anzahl der Funktionen zu zählen, die möglicherweise beschädigt werden, wenn sich die Implementierung der Klasse ändert. In diesem Fall wird deutlich, dass eine Klasse mit n Elementfunktionen stärker gekapselt ist als eine Klasse mit n + 1 Elementfunktionen. Und diese Beobachtung rechtfertigt mein Argument dafür, dass Nicht-Mitglieder-Nicht-Freund-Funktionen den Mitgliedsfunktionen vorgezogen werden

Scott Meyers

Für diejenigen, die mit der C++ - Terminologie nicht vertraut sind:

  • mitgliedsfunktion = Methode
  • nichtmitgliedsfunktion = statische Methode
  • non-friend = nur öffentliche API verwenden
  • non-member non-friend function = statische Methode, die nur die öffentliche API verwendet

Um Ihre Frage zu beantworten:

Kann ich nicht einfach alle statischen Methoden verwenden?

Nein, Sie sollten nicht immer statische Methoden verwenden.

Sie sollten sie jedoch immer dann verwenden, wenn Sie nur die öffentliche öffentliche API einer Klasse verwenden müssen.

3
authchir

Abhängig von der Sprache und dem, was Sie versuchen, kann die Antwort sein, dass es keinen großen Unterschied gibt, aber die static -Version hat etwas mehr Unordnung.

Wie Ihre Beispielsyntax vorschlägt Java oder C #, denke ich, dass Thorbjørn Ravn Andersen zu Recht auf das übergeordnete Problem (mit später Bindung) hinweist. Bei einer statischen Methode gibt es keinen "speziellen" Parameter für späte Bindung basiert darauf, so dass Sie keine späte Bindung haben können.

Tatsächlich ist eine statische Methode nur eine Funktion in einem Modul, wobei dieses Modul denselben Namen wie die Klasse hat - es ist überhaupt keine OOP -Methode).

2
Steve314

Sie besiegen im Grunde den ganzen Punkt von Objekten, wenn Sie dies tun. Es gibt einen guten Grund, warum wir so ziemlich vom prozeduralen Code zum objektorientierten Code übergegangen sind.

Ich würde NIE eine statische Methode deklarieren, die den Klassentyp als Parameter verwendet. Das macht den Code nur komplexer, ohne Gewinn.

2
Loren Pechtel

Hier gibt es viele großartige Antworten, und sie sind viel aufschlussreicher und sachkundiger als alles, was ich jemals als Antwort finden könnte, aber ich habe das Gefühl, dass es etwas gibt, das nicht angesprochen wird:

"Unser Architekt hat entschieden, dass wir alle statischen Methoden für alle APIs verwenden. Seine Argumentation, statische Methoden zu sein, ist gering 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: Das Aufrufen einer statischen Methode hat nur den Aufwand, diese Methode tatsächlich aufzurufen. Das Aufrufen einer nicht statischen (Instanz-) Methode hat den zusätzlichen Aufwand, das Objekt zuerst zu instanziieren und irgendwann die Instanz zu zerstören (entweder manuell oder über eine Form der automatischen Speicherbereinigung, abhängig von der verwendeten Plattform).

Das Stück ein wenig von Devil's Advocate dazu: Wir können noch weiter gehen und Dinge sagen wie:

  • dies kann sehr schlimm werden, wenn für jeden Aufruf der (Instanz-) Methode eine Instanz erstellt wird (anstatt sie nur statisch zu lassen und so aufzurufen).

  • abhängig von der Komplexität des Konstruktors, der Typhyerarchie, anderen Instanzmitgliedern und anderen unbekannten Faktoren kann der zusätzliche Aufwand für den nicht statischen Methodenaufruf variieren und sehr groß werden

In Wahrheit, IMHO, sind die oben genannten Punkte (und der allgemeine Ansatz von "Verwenden wir Statik, weil sie schneller sind") Strohmann-Argumente/Einschätzungen:

  • wenn der Code gut ist und, genauer gesagt, wenn die Instanzen nur bei Bedarf erstellt (und auf optimale Weise zerstört) werden, erhalten Sie keinen zusätzlichen Aufwand durch die Verwendung von Insance-Methoden, wenn dies angebracht ist (denn wenn ja Erstellen Sie nur die benötigten Objekte. Diese wären selbst dann erstellt worden, wenn diese Methode als statisch deklariert worden wäre, wobei else = der gleiche Instanziierungsaufwand ist.

  • wenn Sie die Deklaration statischer Methoden auf diese Weise missbrauchen, können Sie einige Probleme mit Ihrem Code in Bezug auf die Erstellung von Instanzen verbergen (da die Methode statisch ist, kann ein falscher Instanziierungscode bis später unbemerkt bleiben, und das ist nie gut).

2
Shivan Dragon