Frage

Ich habe mit gearbeitet Anbieter in letzter Zeit ziemlich oft, und ich bin auf eine interessante Situation gestoßen, in der ich eine abstrakte Klasse haben wollte, die eine abstrakte statische Methode hatte.Ich habe ein paar Beiträge zu diesem Thema gelesen und es ergab irgendwie Sinn, aber gibt es eine schöne, klare Erklärung?

War es hilfreich?

Lösung

Statische Methoden sind es nicht instanziiert Daher sind sie nur ohne Objektreferenz verfügbar.

Der Aufruf einer statischen Methode erfolgt über den Klassennamen, nicht über eine Objektreferenz, und der Intermediate Language (IL)-Code zum Aufruf 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:

public class A
{
    public static void Test()
    {
    }
}

public class B : A
{
}

Wenn Sie B.Test aufrufen, gehen Sie folgendermaßen vor:

class Program
{
    static void Main(string[] args)
    {
        B.Test();
    }
}

Dann lautet der eigentliche Code in der Main-Methode wie folgt:

.entrypoint
.maxstack 8
L0000: nop 
L0001: call void ConsoleApplication1.A::Test()
L0006: nop 
L0007: ret 

Wie Sie sehen, erfolgt der Aufruf an A.Test, da es die A-Klasse war, die ihn definiert hat, und nicht an B.Test, obwohl Sie den Code auf diese Weise schreiben können.

Wenn du hättest Klassentypen, wie in Delphi, wo Sie eine Variable erstellen können, die auf einen Typ und nicht auf ein Objekt verweist, hätten Sie mehr Verwendung für virtuelle und damit abstrakte statische Methoden (und auch Konstruktoren), aber sie sind nicht verfügbar und daher sind statische Aufrufe nicht verfügbar -virtuell in .NET.

Mir ist klar, dass die IL-Designer zulassen könnten, dass der Code zum Aufrufen von B.Test kompiliert wird und den Aufruf zur Laufzeit auflöst, aber es wäre immer noch nicht virtuell, da Sie dort immer noch eine Art Klassennamen schreiben müssten.

Virtuelle und damit abstrakte Methoden sind nur dann sinnvoll, wenn Sie eine Variable verwenden, die zur Laufzeit viele verschiedene Arten von Objekten enthalten kann, und Sie daher für das aktuelle Objekt, das Sie in der Variablen haben, die richtige Methode aufrufen möchten.Bei statischen Methoden müssen Sie ohnehin einen Klassennamen durchgehen, 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.

Andere Tipps

Statische Methoden können nicht vererbt oder überschrieben werden und können daher nicht abstrakt sein.Da statische Methoden für den Typ und nicht für die Instanz einer Klasse definiert werden, müssen sie explizit für diesen Typ aufgerufen werden.Wenn Sie also eine Methode für eine untergeordnete Klasse aufrufen möchten, müssen Sie zum Aufrufen deren Namen verwenden.Dies macht die Vererbung irrelevant.

Angenommen, Sie könnten für einen Moment statische Methoden erben.Stellen Sie sich dieses Szenario vor:

public static class Base
{
    public static virtual int GetNumber() { return 5; }
}

public static class Child1 : Base
{
    public static override int GetNumber() { return 1; }
}

public static class Child2 : Base
{
    public static override int GetNumber() { return 2; }
}

Welche Methode würde aufgerufen werden, wenn Sie Base.GetNumber() aufrufen?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 lediglich Methoden, die keinen Körper haben und daher nicht aufgerufen werden können.

Ein anderer Befragter (McDowell) sagte, dass Polymorphismus nur für Objektinstanzen funktioniert.Das sollte qualifiziert sein;Es gibt Sprachen, die Klassen als Instanzen eines „Class“- oder „Metaclass“-Typs behandeln.Diese Sprachen unterstützen Polymorphismus sowohl für Instanz- als auch für Klassenmethoden (statische Methoden).

C# ist, wie zuvor Java und C++, keine solche Sprache;Die static Das Schlüsselwort wird explizit verwendet, um anzugeben, dass die Methode statisch und nicht dynamisch/virtuell gebunden ist.

Um die vorherigen Erklärungen zu ergänzen, sind statische Methodenaufrufe an eine bestimmte Methode gebunden Kompilierzeit, was polymorphes Verhalten eher ausschließt.

Hier ist eine Situation, in der definitiv eine Vererbung für statische Felder und Methoden erforderlich ist:

abstract class Animal
{
  protected static string[] legs;

  static Animal() {
    legs=new string[0];
  }

  public static void printLegs()
  {
    foreach (string leg in legs) {
      print(leg);
    }
  }
}


class Human: Animal
{
  static Human() {
    legs=new string[] {"left leg", "right leg"};
  }
}


class Dog: Animal
{
  static Dog() {
    legs=new string[] {"left foreleg", "right foreleg", "left hindleg", "right hindleg"};
  }
}


public static void main() {
  Dog.printLegs();
  Human.printLegs();
}


//what is the output?
//does each subclass get its own copy of the array "legs"?

Wir überschreiben tatsächlich statische Methoden (in Delphi), das ist ein bisschen hässlich, aber für unsere Bedürfnisse funktioniert es ganz gut.

Wir verwenden es, damit die Klassen eine Liste ihrer verfügbaren Objekte ohne die Klasseninstanz haben können. Wir haben beispielsweise eine Methode, die so aussieht:

class function AvailableObjects: string; override;
begin
  Result := 'Object1, Object2';
end; 

Es ist hässlich, aber notwendig. Auf diese Weise können wir genau das instanziieren, was benötigt wird, anstatt alle Klassen nur instanziieren zu lassen, um nach den verfügbaren Objekten zu suchen.

Dies war ein einfaches Beispiel, aber die Anwendung selbst ist eine Client-Server-Anwendung, die alle auf nur einem Server verfügbaren Klassen und mehrere verschiedene Clients hat, die möglicherweise nicht alles benötigen, was der Server hat, und niemals eine Objektinstanz benötigen werden.

Dies ist also viel einfacher zu warten, als für jeden Client eine andere Serveranwendung zu haben.

Ich hoffe, das Beispiel war klar.

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 jedoch nicht statisch abstrakt (oder abstrakt statisch) sein.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top