Ich habe in letzter Zeit einiges mit Anbietern zusammengearbeitet und bin auf eine interessante Situation gestoßen, in der ich eine abstrakte Klasse mit einer abstrakten statischen Methode haben wollte. Ich habe ein paar Beiträge zu diesem Thema gelesen und es hat irgendwie Sinn gemacht, aber gibt es eine schöne klare Erklärung?
c#
.net
language-design
Lomaxx
quelle
quelle
Antworten:
Statische Methoden werden nicht als solche instanziiert , sondern sind nur ohne Objektreferenz verfügbar.
Ein Aufruf einer statischen Methode erfolgt über den Klassennamen, nicht über eine Objektreferenz, und der IL-Code (Intermediate Language) zum Aufrufen ruft die abstrakte Methode über den Namen der Klasse auf, die sie definiert hat, nicht unbedingt über den Namen von die Klasse, die Sie verwendet haben.
Lassen Sie mich ein Beispiel zeigen.
Mit folgendem Code:
Wenn Sie B.Test wie folgt aufrufen:
Dann lautet der tatsächliche Code in der Main-Methode wie folgt:
Wie Sie sehen, wird A.Test aufgerufen, da es die A-Klasse war, die ihn definiert hat, und nicht B.Test, obwohl Sie den Code auf diese Weise schreiben können.
Wenn Sie Klassentypen wie in Delphi hätten, in denen Sie eine Variable erstellen können, die sich auf einen Typ und nicht auf ein Objekt bezieht, hätten Sie mehr Verwendung für virtuelle und damit abstrakte statische Methoden (und auch Konstruktoren), aber diese sind nicht verfügbar und Daher sind statische Aufrufe in .NET nicht virtuell.
Mir ist klar, dass die IL-Designer zulassen könnten, dass der Code kompiliert wird, um B.Test aufzurufen, und den Aufruf zur Laufzeit auflösen, aber er wäre immer noch nicht virtuell, da Sie dort immer noch einen Klassennamen schreiben müssten.
Virtuelle und damit abstrakte Methoden sind nur dann nützlich, wenn Sie eine Variable verwenden, die zur Laufzeit viele verschiedene Objekttypen enthalten kann, und Sie daher die richtige Methode für das aktuelle Objekt in der Variablen aufrufen möchten. Bei statischen Methoden müssen Sie ohnehin einen Klassennamen durchlaufen, sodass die genaue aufzurufende Methode zur Kompilierungszeit bekannt ist, da sie sich nicht ändern kann und wird.
Daher sind virtuelle / abstrakte statische Methoden in .NET nicht verfügbar.
quelle
Test()
in istA
eher als abstrakt zu sein und möglicherweise definiert inB
\.Car
Typ mit einer virtuellen statischenCreateFromDescription
Factory-Methode hatte, konnte Code, der einenCar
eingeschränkten generischen Typ akzeptierte,T
aufgerufen werdenT.CreateFromDescription
, um ein Auto vom Typ zu erzeugenT
. Ein solches Konstrukt könnte innerhalb der CLR ziemlich gut unterstützt werden, wenn jeder Typ, der eine solche Methode definiert, eine statische Singleton-Instanz einer verschachtelten Klasse generisch enthält, die die virtuellen "statischen" Methoden enthält.Statische Methoden können nicht vererbt oder überschrieben werden, weshalb sie nicht abstrakt sein können. Da statische Methoden für den Typ und nicht für die Instanz einer Klasse definiert sind, müssen sie für diesen Typ explizit aufgerufen werden. Wenn Sie also eine Methode für eine untergeordnete Klasse aufrufen möchten, müssen Sie ihren Namen verwenden, um sie aufzurufen. Dies macht die Vererbung irrelevant.
Angenommen, Sie könnten für einen Moment statische Methoden erben. Stellen Sie sich dieses Szenario vor:
Wenn Sie Base.GetNumber () aufrufen, welche Methode würde aufgerufen? Welcher Wert wurde zurückgegeben? Es ist ziemlich leicht zu erkennen, dass die Vererbung ohne das Erstellen von Instanzen von Objekten ziemlich schwierig ist. Abstrakte Methoden ohne Vererbung sind nur Methoden, die keinen Körper haben und daher nicht aufgerufen werden können.
quelle
int DoSomething<T>() where T:Base {return T.GetNumber();}
. Es erscheint nützlich, wennDoSomething<Base>()
fünf zurückgegeben werden könnten, währendDoSomething<Child2>()
zwei zurückgegeben werden könnten . Eine solche Fähigkeit wäre nicht nur für Spielzeugbeispiele nützlich, sondern auch für etwasclass Car {public static virtual Car Build(PurchaseOrder PO);}
, bei dem jede Klasse, vonCar
der abgeleitet wird, eine Methode definieren müsste, mit der eine Instanz bei einer Bestellung erstellt werden könnte.Ein anderer Befragter (McDowell) sagte, dass Polymorphismus nur für Objektinstanzen funktioniert. Das sollte qualifiziert sein; Es gibt Sprachen, die Klassen als Instanzen eines Typs "Klasse" oder "Metaklasse" behandeln. Diese Sprachen unterstützen den Polymorphismus sowohl für Instanz- als auch für Klassenmethoden (statisch).
C # ist wie Java und C ++ zuvor keine solche Sprache. Das
static
Schlüsselwort wird explizit verwendet, um anzuzeigen, dass die Methode eher statisch als dynamisch / virtuell gebunden ist.quelle
Hier ist eine Situation, in der definitiv eine Vererbung für statische Felder und Methoden erforderlich ist:
quelle
legs
sollte eine statische abstrakte Eigenschaft sein.Um die vorherigen Erläuterungen zu ergänzen, werden statische Methodenaufrufe zur Kompilierungszeit an eine bestimmte Methode gebunden , wodurch polymorphes Verhalten eher ausgeschlossen wird.
quelle
Wir überschreiben tatsächlich statische Methoden (in Delphi), es ist ein bisschen hässlich, aber es funktioniert gut für unsere Bedürfnisse.
Wir verwenden es, damit die Klassen eine Liste ihrer verfügbaren Objekte ohne die Klasseninstanz haben können. Wir haben beispielsweise eine Methode, die folgendermaßen aussieht:
Es ist hässlich, aber notwendig. Auf diese Weise können wir genau das instanziieren, was benötigt wird, anstatt alle Klassen instanziieren zu lassen, nur um nach den verfügbaren Objekten zu suchen.
Dies war ein einfaches Beispiel, aber die Anwendung selbst ist eine Client-Server-Anwendung, bei der alle Klassen auf nur einem Server verfügbar sind und mehrere verschiedene Clients, die möglicherweise nicht alles benötigen, was der Server hat, und niemals eine Objektinstanz benötigen.
Dies ist also viel einfacher zu warten, als für jeden Client eine andere Serveranwendung zu haben.
Hoffe das Beispiel war klar.
quelle
Die abstrakten Methoden sind implizit virtuell. Abstrakte Methoden erfordern eine Instanz, statische Methoden haben jedoch keine Instanz. Sie können also eine statische Methode in einer abstrakten Klasse haben, sie kann einfach nicht statisch abstrakt (oder abstrakt statisch) sein.
quelle