Bei der Beantwortung dieser Frage herrschte allgemeiner Konsens darüber, dass statische Methoden nicht überschrieben werden sollen (und statische Funktionen in C # daher nicht virtuell oder abstrakt sein können). Dies ist jedoch nicht nur in C # der Fall. Java verbietet dies auch und C ++ scheint es auch nicht zu mögen. Ich kann mir jedoch viele Beispiele für statische Funktionen vorstellen, die ich in einer untergeordneten Klasse überschreiben möchte (z. B. Factory-Methoden). Theoretisch gibt es zwar Möglichkeiten, sie zu umgehen, aber keine davon ist sauber oder einfach.
Warum sollten statische Funktionen nicht überschreibbar sein?
object-oriented-design
abstract-class
static-methods
PixelArtDragon
quelle
quelle
self
Zeiger, der auf die Klasse und nicht auf eine Instanz der Klasse verweist.Antworten:
Bei den statischen Methoden besteht keine Aufgabe darin, den Übersteuerungsmechanismus ordnungsgemäß zu steuern.
Der Mechanismus der normalen virtuellen Klasse / Instanz-Methode ermöglicht die fein abgestimmte Steuerung von Überschreibungen wie folgt: Jedes reale Objekt ist eine Instanz von genau einer Klasse. Diese Klasse bestimmt das Verhalten der Überschreibungen. es bekommt immer den ersten Riss bei virtuellen Methoden. Sie kann dann die übergeordnete Methode zum richtigen Zeitpunkt für die Implementierung aufrufen. Jede übergeordnete Methode ruft dann auch ihre übergeordnete Methode auf. Dies führt zu einer Kaskade von übergeordneten Aufrufen, die einen der Begriffe der Wiederverwendung von Code erfüllt, für den die Objektorientierung bekannt ist. (Hier wird der Code der Basis- / Superklasse in relativ komplexer Weise wiederverwendet. Ein weiterer orthogonaler Begriff der Wiederverwendung von Code in OOP besteht darin, einfach mehrere Objekte derselben Klasse zu haben.)
Basisklassen können von verschiedenen Unterklassen wiederverwendet werden und jede kann problemlos koexistieren. Jede Klasse, die verwendet wird, um Objekte zu instanziieren, die ihr eigenes Verhalten diktieren, friedlich und gleichzeitig mit den anderen koexistieren. Der Client hat die Kontrolle darüber, welches Verhalten er wann haben möchte, indem er wählt, mit welcher Klasse ein Objekt instanziiert und wie gewünscht an andere weitergegeben wird.
(Dies ist kein perfekter Mechanismus, da man natürlich immer Fähigkeiten identifizieren kann, die nicht unterstützt werden, weshalb Muster wie die Factory-Methode und die Abhängigkeitsinjektion überlagert sind.)
Wenn wir also eine Override-Funktion für die Statik erstellen würden, ohne etwas anderes zu ändern, hätten wir Schwierigkeiten, die Overrides zu bestellen. Es ist schwierig, einen begrenzten Kontext für die Anwendbarkeit der Außerkraftsetzung zu definieren, sodass die Außerkraftsetzung eher global als lokal wie bei Objekten erfolgt. Es gibt kein Instanzobjekt, um das Verhalten zu ändern. Wenn also jemand die statische Methode aufgerufen hat, die zufällig von einer anderen Klasse überschrieben wurde, sollte die Überschreibung dann die Kontrolle erhalten oder nicht? Wenn es mehrere solcher Überschreibungen gibt, wer erhält zuerst die Kontrolle? zweite? Bei Überschreibungen von Instanzobjekten haben diese Fragen alle sinnvolle und gut begründete Antworten, bei statischen Fragen jedoch nicht.
Überschreibungen für Statik wären im Wesentlichen chaotisch, und solche Vorgänge wurden bereits durchgeführt.
Beispielsweise verwendeten das Mac OS System 7 und frühere Versionen einen Trap-Patch-Mechanismus, um das System zu erweitern, indem die Kontrolle über von Anwendungen ausgeführte Systemaufrufe vor dem Betriebssystem erlangt wurde. Sie können sich die Systemaufruf-Patch-Tabelle als ein Array von Funktionszeigern vorstellen , ähnlich einer vtable für Instanzobjekte , mit der Ausnahme, dass es sich um eine einzelne globale Tabelle handelt.
Dies verursachte den Programmierern aufgrund der ungeordneten Art des Trap-Patches ungeahnten Kummer. Wer zuletzt die Falle flicken musste, gewann im Grunde genommen, auch wenn er es nicht wollte. Jeder Patcher des Traps erfasste den vorherigen Trap-Wert für eine Art übergeordneter Aufruffunktion, die äußerst zerbrechlich war. Das Entfernen eines Trap-Patches, wenn Sie nicht mehr über einen Systemaufruf Bescheid wissen mussten, wurde als fehlerhaft eingestuft, da Sie nicht über die erforderlichen Informationen zum Entfernen Ihres Patches verfügten Sie).
Dies soll nicht heißen, dass es unmöglich wäre, einen Mechanismus zum Überschreiben von Statik zu erstellen, aber ich würde es wahrscheinlich vorziehen, stattdessen die statischen Felder und statischen Methoden in Instanzfelder und Instanzmethoden von Metaklassen umzuwandeln, so dass das normale Objekt Dann würden Orientierungstechniken angewendet. Beachten Sie, dass es auch Systeme gibt, die dies tun: CSE 341: Smalltalk-Klassen und Metaklassen ; Siehe auch: Was ist das Smalltalk-Äquivalent der Java-Statik?
Ich versuche zu sagen, dass Sie einige ernsthafte Sprachfeatures entwerfen müssten, damit es auch einigermaßen gut funktioniert. Zum Beispiel wurde eine naive Herangehensweise unternommen, die hinkte, aber sehr problematisch war und möglicherweise (dh ich würde argumentieren) architektonisch fehlerhaft war, indem eine unvollständige und schwer zu verwendende Abstraktion bereitgestellt wurde.
Wenn Sie mit dem Entwerfen der Funktion für statische Überschreibungen fertig sind, haben Sie möglicherweise gerade eine Form von Metaklassen erfunden, die eine natürliche Erweiterung von OOP in / für klassenbasierte Methoden darstellt. Es gibt also keinen Grund, dies nicht zu tun - und einige Sprachen tun dies tatsächlich. Vielleicht ist es nur eine Randbedingung, dass eine Reihe von Sprachen dies nicht tun.
quelle
this.instanceMethod()
eine dynamische Auflösung. Wennself.staticMethod()
also die gleiche Auflösung vorliegt , nämlich dynamisch, wäre dies keine statische Methode mehr.Das Überschreiben hängt vom virtuellen Versand ab: Sie verwenden den Laufzeittyp des
this
Parameters, um zu entscheiden, welche Methode aufgerufen werden soll. Eine statische Methode hat keinenthis
Parameter, daher gibt es nichts zu versenden.Einige Sprachen, insbesondere Delphi und Python, haben einen Zwischenbereich, der dies ermöglicht: Klassenmethoden. Eine Klassenmethode ist keine gewöhnliche Instanzmethode, aber sie ist auch nicht statisch. Es erhält einen
self
Parameter (amüsanterweise bezeichnen beide Sprachen denthis
Parameterself
), der auf den Objekttyp selbst und nicht auf eine Instanz dieses Typs verweist. Mit diesem Wert steht Ihnen jetzt ein Typ zur Verfügung, auf dem Sie den virtuellen Versand durchführen können.Leider hat weder die JVM noch die CLR etwas Vergleichbares.
quelle
self
Haben die verwendeten Sprachen Klassen als tatsächliche, instanziierte Objekte mit überschreibbaren Methoden - Smalltalk natürlich, Ruby, Dart, Objective C, Self, Python? Im Vergleich zu den Sprachen nach C ++, in denen Klassen keine erstklassigen Objekte sind, auch wenn es einen Reflektionszugriff gibt?virtual
genau wie Instanzmethoden explizit deklariert und dann in einer abgeleiteten Klasse überschrieben werden.Du fragst
Ich frage
Bestimmte Sprachen zwingen Sie, die Show in einer statischen Methode zu starten. Aber danach kann man wirklich sehr viele Probleme lösen, ohne statischere Methoden.
Manche Menschen wenden statische Methoden immer dann an, wenn in einem Objekt keine Abhängigkeit vom Zustand besteht. Einige Leute benutzen gerne statische Methoden für die Konstruktion anderer Objekte. Manche Leute meiden statische Methoden so oft wie möglich.
Keiner dieser Leute ist falsch.
Wenn es überschreibbar sein soll, beenden Sie einfach die statische Kennzeichnung. Nichts wird kaputt gehen, weil ein staatenloses Objekt herumfliegt.
quelle
_start()
Symbol unter Linux). In diesem Beispiel ist die ausführbare Datei das Objekt (sie hat eine eigene "Dispatch-Tabelle" und alles) und der Einstiegspunkt ist die dynamisch versendete Operation. Daher ist der Einstiegspunkt eines Programms von außen betrachtet von Natur aus virtuell und kann auch von innen betrachtet auf einfache Weise virtuell aussehen.Es geht nicht um "sollte".
"Overriding" bedeutet " dynamisch versenden ". "Statische Methode" bedeutet "statisch versenden". Wenn etwas statisch ist, kann es nicht überschrieben werden. Wenn etwas überschrieben werden kann, ist es nicht statisch.
Ihre Frage ist ziemlich ähnlich zu fragen: "Warum sollten Dreiräder nicht vier Räder haben können?" Die Definition von "Dreirad" ist, dass drei Räder hat. Wenn es ein Dreirad ist, kann es keine vier Räder haben. Wenn es vier Räder hat, kann es kein Dreirad sein. Ebenso ist die Definition der "statischen Methode", dass sie statisch versendet wird. Wenn es sich um eine statische Methode handelt, kann sie nicht dynamisch verteilt werden. Wenn sie dynamisch verteilt werden kann, kann sie keine statische Methode sein.
Es ist natürlich durchaus möglich, Klassenmethoden zu haben , die überschrieben werden können. Sie können auch eine Sprache wie Ruby verwenden, in der Klassen wie jedes andere Objekt Objekte sind und daher über Instanzmethoden verfügen, sodass Klassenmethoden nicht mehr erforderlich sind. (Ruby hat nur eine Art von Methoden: Instanzmethoden. Es gibt keine Klassenmethoden, statischen Methoden, Konstruktoren, Funktionen oder Prozeduren.)
quelle
In C # rufen Sie statische Member immer über die Klasse auf, z . B.
BaseClass.StaticMethod()
nichtbaseObject.StaticMethod()
. Wenn Sie alsoChildClass
vonBaseClass
undchildObject
eine Instanz von geerbt habenChildClass
, können Sie Ihre statische Methode nicht von aufrufenchildObject
. Sie müssen immer explizit die reale Klasse verwenden, damit einestatic virtual
nur keinen Sinn ergibt.Sie können dieselbe
static
Methode in Ihrer untergeordneten Klasse neu definieren und dasnew
Schlüsselwort verwenden.Wenn es möglich wäre anzurufen
baseObject.StaticMethod()
, wäre Ihre Frage sinnvoll.quelle