Was ist der Grund dafür, bestimmte Methoden für Datentypen statisch zu machen?
In C# gibt es beispielsweise statische Methoden, um festzustellen, ob eine Zeichenfolge null oder leer ist, ein Element in einem Array zu finden, ein Array zu löschen usw. Es gibt jedoch eine Instanzmethode zum Ersetzen von Zeichen in einer Zeichenfolge, und zwar sowohl statisch als auch instanz Methoden zum Kopieren von Elementen zwischen Arrays.
In ähnlicher Weise gibt es in Python Funktionen, um die Länge einer Liste zu ermitteln, eine Liste zu filtern usw., aber Instanzmethoden, um den Index eines Elements zu finden und die Liste zu kopieren.
Im Gegensatz dazu ist in JavaScript so ziemlich jede Operation, die ich für einen eingebauten Datentyp ausführen muss, über die Instanzmethode oder -eigenschaft zugänglich.
Was ist also der Grund dafür, bestimmte Dinge statisch zu machen und andere nicht?
BEARBEITEN : Um es klar zu sagen, ich verstehe den Zweck statischer Methoden. Meine Frage zielt eher darauf ab, warum bestimmte Methoden als statisch geschrieben werden, wenn sie als Instanzmethoden geschrieben werden könnten. Wie Find
für Arrays und Format
Strings in C# und filter
und len
in Python.
Antworten
BEARBEITEN : Die Frage wurde verfeinert, daher werde ich meine Antwort verfeinern, aber die vorherige unten lassen, um die Kommentare nicht irrelevant zu machen.
Es kann mehrere Gründe geben, eine Methode als statische Methode anstelle einer Instanzmethode zu implementieren, wobei verschiedene Sprachen oder Frameworks möglicherweise unterschiedliche Begründungen haben:
Die öffentliche Schnittstelle eines Objekts ist ein Vertrag. Wenn Ihr
Array
Typ eineSort
Methode verfügbar macht, muss von nun an jedes Array, unabhängig von Typ oder Version der Sprache, diese unterstützen. Wenn an jedochArray
nur eine Darstellung von Daten im Speicher mit einem dünnen Vertrag ist und die Logik in eine Klasse wie verschobenArray.Sort
wird, gibt Ihnen dies mehr Flexibilität, um Ihr Verhalten zu erweitern oder zu ändern, ohne die Kompatibilität zu beeinträchtigen.Siehe dieses Zitat aus Bob Martins Clean Code :
Objekte legen Verhalten offen und verbergen Daten; Datenstruktur legt Daten offen und hat kein signifikantes Verhalten"
In diesem Fall ist die List
Klasse eine Klasse, die das Verhalten offenlegt – sie verbirgt ihre Daten (sie ist als größenveränderbares Array implementiert, aber das ist ein Implementierungsdetail), stellt jedoch die Funktionalität bereit. Eine int[]
ist jedoch eine Datenstruktur. Es ist ein sequentiell zugewiesener int
Block. Es hat eine Length
Eigenschaft, weil es Teil seiner Daten ist, aber es hat nicht viel Verhalten – das Verhalten wird an eine Klasse ausgelagert, die damit arbeitet.
- Es könnte eine stilistische Entscheidung sein. Python ist keine reine OO-Sprache und verfügt möglicherweise nicht über die Java/C#-Garantie „Alles ist ein Objekt“. Daher hat es sich für die Verwendung solcher Sprachfunktionen entschieden
len()
, die unabhängig davon verwendet werden können, ob ihr Parameter eine Objektinstanz ist oder nicht.
Vorherige Antwort
Das Grundprinzip hinter statischen Methoden in C# besteht darin, Methoden zu haben, die an einen Typ , aber nicht an eine Instanz gebunden sind . Dafür kann es mehrere Gründe geben:
- Methoden, die sowohl auf einer Instanz als auch auf operieren können
null
, wiestring.IsNullOrEmpty
, können natürlich keine Instanzmethoden sein - weil es möglicherweise keine Instanz gibt. - Factory-Methoden, die eine Instanz erstellen, haben ebenfalls keine Instanz, von der aus sie aufgerufen werden können. Beispielsweise gibt die veraltete statische
WebRequest.Create()
Methode von jemandem eine neue Instanz eines Typs zurück, der von abgeleitet istWebRequest
. - Obwohl es leicht zu vergessen ist, hat .NET eine unterschiedliche Behandlung für einen nativen ganzzahligen Typ (
int i =5
) und einen umrahmten Referenztyp (object boxed = 5
). Wenn Sie eine Methode für einen Werttyp (int i = 5; t.ToString();
) aufrufen, entstehen Ihnen Boxing-Kosten. Aus diesem Grund werden einige Operationen nicht als Methode für ein Objekt definiert, sondern als statische Methode, die einen Wert akzeptiert. Aus diesem Grund sind mathematische Operationen wieMath.Abs
bei den Boxed-Typen nicht als Methoden definiert, sondern als statische Funktionen, die Werte empfangen und zurückgeben. - Manchmal werden statische Methoden verwendet, um einen Typ zu "konfigurieren", nicht eine bestimmte Instanz, sondern das Verhalten dieses Typs im System. Konfiguriert beispielsweise
[ServicePointManager.SetTcpKeepAlive()][1]
das Verhalten aller Klassen, die den gemeinsam genutzten HTTP(s)-Stack in .NET verwenden, sodass Sie sie alle über diese statischen Methoden konfigurieren können.
Statische Methoden sind sehr sinnvoll
- wenn die Methode mit dem Typ verwandt ist, aber keine vorhandene Instanz erfordert; oder
- wenn die Sprache Namensräume nur über Klassen unterstützt.
C# unterstützt nur Funktionen als Mitglieder von Klassen, daher sollten Hilfsfunktionen als statische Methoden geschrieben werden. Die C# Math
-Klasse ist ein Paradebeispiel.
JavaScript hat keine Klassen, aber jede nicht lokale Variable ist einem Objekt zugeordnet – im Browser sind die meisten APIs über das window
Objekt zugänglich. Es gibt jedoch Methoden, die über ein klassenähnliches Objekt zugänglich sind, zB Array.isArray(x)
.
Python hat ein eigenwilliges Design, das hauptsächlich objektorientiert ist, aber einige eingebaute Funktionen wie len()
oder iter()
hat, hauptsächlich aus historischen Gründen. Unter der Haube rufen sie tatsächliche Methoden auf, zB iter(x)
is normalerweise x.__iter__()
, mit einem Fallback für Objekte, die wie eine Liste indiziert werden können.
Interessanter sind Methoden, die static
nicht wegen Macken der Sprache, sondern weil es sinnvoll ist. Konstruktor- oder Factory-ähnliche Methoden sind das klassische Beispiel, bei dem wir kein vorhandenes Objekt haben, für das wir eine Methode aufrufen könnten. Einige Funktionen arbeiten auch nicht mit genau einem Objekt, zB arbeiten sie String.IsNullOrEmpty(x)
mit null oder einem Objekt. Dies funktioniert nicht als Methode, x.IsNullOrEmpty()
würde zB eine Ausnahme auslösen, wenn es null ist! Die Array.isArray(x)
Methode in JS ist ein weiteres großartiges Beispiel: Wir möchten isArray(x)
Objekte jeden Typs aufrufen, nicht nur Arrays. Daher funktioniert eine Instanzmethode nur, wenn sie Teil des Prototyps jedes Objekts ist.