it-swarm-eu.dev

Warum und wann sollte ich eine Klasse "statisch" machen? Was ist der Zweck des Schlüsselworts "statisch" für Klassen?

Das Schlüsselwort static für ein Mitglied in vielen Sprachen bedeutet, dass Sie keine Instanz dieser Klasse erstellen sollten, um Zugriff auf dieses Mitglied zu erhalten. Ich sehe jedoch keine Rechtfertigung dafür, eine ganze Klasse static zu erstellen. Warum und wann sollte ich eine Klasse static erstellen?

Welche Vorteile bringt es mir, eine Klasse static zu erstellen? Ich meine, nachdem man eine statische Klasse deklariert hat, sollte man immer noch alle Mitglieder, auf die er ohne Instanziierung Zugriff haben möchte, als statisch deklarieren.

Dies bedeutet, dass beispielsweise die Klasse Math als normal (nicht statisch) deklariert werden kann, ohne dass sich dies auf den Code der Entwickler auswirkt. Mit anderen Worten, eine Klasse statisch oder normal zu machen, ist für Entwickler transparent.

48
Saeed Neamati

Es macht den Benutzern klar, wie die Klasse verwendet wird. Zum Beispiel wäre es völliger Unsinn, den folgenden Code zu schreiben:

Math m = new Math();

C # muss verbietet dies, aber da es keinen Zweck erfüllt, kann es dem Benutzer genauso gut mitgeteilt werden. Bestimmte Personen (einschließlich mir) halten an der Philosophie fest, dass Programmiersprachen (und APIs…) so restriktiv wie möglich sein sollten, damit sie nur schwer falsch verwendet werden können: Die einzigen zulässigen Operationen sind dann diejenigen, die sinnvoll und (hoffentlich) korrekt sind.

34
Konrad Rudolph

StackOverflow hat eine großartige Diskussion zu diesem Thema . Zum leichteren Nachschlagen kopiere ich es hier und füge es im Namen seines Autors ein Mark S. Rasmussen :

Ich schrieb meine Gedanken zu statischen Klassen in einem früheren Thread :

Ich liebte Utility-Klassen, die mit statischen Methoden gefüllt waren. Sie haben eine große Konsolidierung von Hilfsmethoden vorgenommen, die sonst herumliegen und Redundanz und Wartungshölle verursachen würden. Sie sind sehr einfach zu bedienen, keine Instanziierung, keine Entsorgung, nur Feuer und Vergessen. Ich denke, dies war mein erster unabsichtlicher Versuch, eine serviceorientierte Architektur zu erstellen - viele zustandslose Services, die nur ihre Arbeit erledigt haben und sonst nichts. Wenn ein System wächst, kommen jedoch Drachen.

Polymorphismus

Nehmen wir an, wir haben die Methode UtilityClass.SomeMethod, die gerne mitschwirrt. Plötzlich müssen wir die Funktionalität leicht ändern. Die meisten Funktionen sind gleich, aber wir müssen trotzdem einige Teile ändern. Wäre es keine statische Methode gewesen, könnten wir eine Ableitungsklasse erstellen und den Methodeninhalt nach Bedarf ändern. Da es sich um eine statische Methode handelt, können wir dies nicht. Sicher, wenn wir nur vor oder nach der alten Methode Funktionen hinzufügen müssen, können wir eine neue Klasse erstellen und die alte darin aufrufen - aber das ist nur grob.

Probleme mit der Benutzeroberfläche

Statische Methoden können aus logischen Gründen nicht über Schnittstellen definiert werden. Und da wir statische Methoden nicht überschreiben können, sind statische Klassen nutzlos, wenn wir sie über ihre Schnittstelle weitergeben müssen. Dies macht es uns unmöglich, statische Klassen als Teil eines Strategiemusters zu verwenden. Wir können einige Probleme beheben, indem wir Delegierte anstelle von Schnittstellen übergeben.

Testen

Dies geht grundsätzlich Hand in Hand mit den oben genannten Schnittstellenproblemen. Da unsere Möglichkeiten zum Austausch von Implementierungen sehr begrenzt sind, haben wir auch Probleme, Produktionscode durch Testcode zu ersetzen. Auch hier können wir sie einpacken, aber wir müssen große Teile unseres Codes ändern, um Wrapper anstelle der eigentlichen Objekte akzeptieren zu können.

Fördert Blobs

Da statische Methoden normalerweise als Dienstprogrammmethoden verwendet werden und Dienstprogrammmethoden normalerweise unterschiedliche Zwecke haben, erhalten wir schnell eine große Klasse mit nicht kohärenten Funktionen - idealerweise sollte jede Klasse einen einzigen Zweck innerhalb des Systems haben. Ich hätte viel lieber eine fünffache Klasse, solange ihre Zwecke genau definiert sind.

Parameterkriechen

Zunächst könnte diese kleine niedliche und unschuldige statische Methode einen einzelnen Parameter annehmen. Mit zunehmender Funktionalität werden einige neue Parameter hinzugefügt. Bald werden weitere Parameter hinzugefügt, die optional sind, sodass wir Überladungen der Methode erstellen (oder einfach Standardwerte in Sprachen hinzufügen, die sie unterstützen). In Kürze haben wir eine Methode, die 10 Parameter akzeptiert. Nur die ersten drei sind wirklich erforderlich, die Parameter 4-7 sind optional. Wenn jedoch Parameter 6 angegeben wird, müssen auch 7-9 ausgefüllt werden ... Hätten wir eine Klasse mit dem einzigen Zweck erstellt, das zu tun, was diese statische Methode getan hat, könnten wir dies lösen, indem wir die erforderlichen Parameter in der Konstruktor und Ermöglichen, dass der Benutzer optionale Werte über Eigenschaften oder Methoden zum gleichzeitigen Festlegen mehrerer voneinander abhängiger Werte festlegt. Wenn eine Methode auf diese Komplexität angewachsen ist, muss sie höchstwahrscheinlich sowieso in ihrer eigenen Klasse sein.

Verbraucher müssen ohne Grund eine Instanz von Klassen erstellen

Eines der häufigsten Argumente ist, warum Verbraucher unserer Klasse eine Instanz zum Aufrufen dieser einzelnen Methode erstellen müssen, ohne die Instanz danach zu verwenden. Das Erstellen einer Instanz einer Klasse ist in den meisten Sprachen eine sehr, sehr billige Operation, daher ist Geschwindigkeit kein Problem. Das Hinzufügen einer zusätzlichen Codezeile zum Verbraucher ist kostengünstig, um den Grundstein für eine viel wartbarere Lösung in der Zukunft zu legen. Wenn Sie das Erstellen von Instanzen vermeiden möchten, erstellen Sie einfach einen Singleton-Wrapper Ihrer Klasse, der eine einfache Wiederverwendung ermöglicht. Dies setzt jedoch voraus, dass Ihre Klasse zustandslos ist. Wenn es nicht zustandslos ist, können Sie dennoch statische Wrapper-Methoden erstellen, die alles verarbeiten und Ihnen auf lange Sicht alle Vorteile bieten. Schließlich können Sie auch eine Klasse erstellen, die die Instanziierung verbirgt, als wäre es ein Singleton: MyWrapper.Instance ist eine Eigenschaft, die nur new MyClass () zurückgibt.

Nur ein Sith handelt absolut

Natürlich gibt es Ausnahmen von meiner Abneigung gegen statische Methoden. Echte Utility-Klassen, die kein Aufblähungsrisiko darstellen, eignen sich hervorragend für statische Methoden - beispielsweise System.Convert. Wenn es sich bei Ihrem Projekt um ein Einzelprojekt handelt, für das keine zukünftigen Wartungsarbeiten erforderlich sind, ist die Gesamtarchitektur nicht sehr wichtig - statisch oder nicht statisch, spielt keine Rolle - die Entwicklungsgeschwindigkeit jedoch.

Standards, Standards, Standards!

Die Verwendung von Instanzmethoden hindert Sie nicht daran, auch statische Methoden zu verwenden und umgekehrt. Solange die Differenzierung begründet und standardisiert ist. Es gibt nichts Schlimmeres, als einen Blick auf eine Business-Schicht zu werfen, die sich über verschiedene Implementierungsmethoden erstreckt.

25
Rick

Ich bin überrascht, dass niemand sonst erwähnt hat, dass static Klassen Erweiterungsmethoden erlauben - einen vorhandenen Typ sicher erweitern (einschließlich Hinzufügen von Methodendefinitionen zu Schnittstellen ) die du nicht besitzt. Zum Beispiel, was in Scala ist)

trait MyFoo {
  def foo: Int
  def plusFoo(a: Int) = foo + a
}

kann in C # ausgedrückt werden als

public interface IMyFoo {
  int Foo();
}

public static class MyFooExtensions {
  public static int PlusFoo(this IMyFoo f, int a) {
    return f.Foo() + a;
  }
}
16
Frank Shearar

Für mich ist eine statische Klasse (in C #) so etwas wie das Aufrufen einer Funktion.

Zum Beispiel

public static string DoSomething(string DoSomethingWithThisString){}

Ich gebe eine Zeichenfolge ein und bekomme eine Zeichenfolge zurück. Alles ist in dieser Methode enthalten. Kein Zugriff auf Mitgliedsvariable usw.

Ehrlich gesagt, hauptsächlich für mich war es, die Codezeilen zu verringern:

Warum machen:

MyClass class = new MyClass();
String s = class.DoSomething("test");

Wenn ich das kann:

String s = MyClass.DoSomething("test");

In diesen Fällen würde ich statische Klassen verwenden, wenn ich etwas ohne die Notwendigkeit einer Klasse tun wollte und weniger tippen würde.

Mark S. Punkte sind gültig, aber wenn ich einige Dienstprogrammmethoden habe, ist es einfacher vorzutäuschen, dass ich eine Funktion aufrufe, um sie als einen Liner zu referenzieren.

Das mag simpel sein, aber so habe ich meistens static verwendet.

3
Jon Raynor