Frage

ich vor kurzem lief in ein Problem, wo es scheint, dass ich eine ‚statische abstrakt‘ Methode benötigen. Ich weiß, warum es unmöglich ist, aber wie kann ich diese Einschränkung umgehen?

Zum Beispiel habe ich eine abstrakte Klasse, die eine Beschreibung Zeichenfolge hat. Da diese Zeichenfolge für alle Instanzen üblich sind, wird es als statisch markiert, aber ich möchte verlangen, dass alle von dieser Klasse abgeleiteten Klassen ihre eigene Beschreibung Eigenschaft bieten, damit ich es als abstrakt markiert:

abstract class AbstractBase
{
    ...
    public static abstract string Description{get;}
    ...
}

Es wird natürlich nicht kompilieren. Ich dachte an Schnittstellen aber Schnittstellen nicht statische Methode Signaturen enthalten.

Soll ich es einfach nicht statisch, und immer eine Instanz erhalten, um diese klassenspezifische Informationen?

Irgendwelche Ideen?

War es hilfreich?

Lösung

Die Kombination von statischen und abstrakt ist etwas sinnlos, ja. Die Idee hinter statisch ist braucht man nicht eine Instanz der Klasse vorlegen, um das betreffende Mitglied zu verwenden; jedoch mit abstrakten, erwartet man eine Instanz einer abgeleiteten Klasse zu sein, die eine konkrete Umsetzung bereitstellt.

kann ich sehen, warum Sie diese Art von Kombination wollen würden, aber die Tatsache ist die einzige Wirkung, die Umsetzung Verwendung von ‚this‘ oder jegliche nicht-statischen Elementen zu leugnen wäre. Das heißt, die Elternklasse eine Beschränkung bei der Umsetzung der abgeleiteten Klasse diktieren würde, auch wenn es zwischen dem Aufruf einem abstrakten oder ‚statisches abstraktes‘ Elemente (wie beide müßten ein konkretes Beispiel, um herauszufinden, was die Umsetzung zu verwenden) kein zugrunde liegenden Unterschied ist

Andere Tipps

Sie kann nicht.

Der Ort, dies zu tun ist mit Attributen.

Eg

[Name("FooClass")]
class Foo
{
}

Wenn Sie nichts dagegen nicht auf Implementierungen aufzuschieben sinnvoll die Beschreibung Eigenschaft zu implementieren, können Sie einfach tun

public abstract string ClassDescription {get; } 
// ClassDescription is more intention-revealing than Description

Und Klassen Umsetzung etwas wie dies tun würde:

static string classDescription="My Description for this class";
override string  ClassDescription { get { return classDescription; } }

Dann werden Ihre Klassen erforderlich, den Vertrag mit einer Beschreibung zu folgen, aber sie lassen es ihnen es sinnvoll zu tun. Es gibt keine Möglichkeit, eine Implementierung in einer objektorientierten Art und Weise anzugeben (außer durch grausame, fragile Hacks).

Doch meiner Meinung ist diese Beschreibung Klasse Metadaten, so würde ich es vorziehen, das Attribut Mechanismus zu verwenden, wie andere beschrieben haben. Wenn Sie besonders besorgt über mehrere Verwendungen der Reflexion sind, erstellen Sie ein Objekt, das über das Attribut reflektiert, die Sie mit betroffen sind, und speichern Sie ein Wörterbuch zwischen dem Typ und der Beschreibung. Das wird die Reflexion (außer Laufzeit Typ Inspektion, die gar nicht so schlecht ist) minimieren. Das Wörterbuch kann als Mitglied jeglicher Klasse gespeichert werden, die normalerweise diese Information benötigt, oder, wenn Kunden auf der Domain es erfordern, über einen Singleton oder Kontextobjekt.

Wenn es statisch ist, gibt es nur eine Instanz der Variablen ist, sehe ich nicht, wie die Vererbung Sinn machen würden, wenn wir könnten tun, was Sie mit statischen Vars in abgeleiteten Klassen erreichen möchten. Ich persönlich denke, Sie zu weit gehen zu versuchen, eine Instanz var zu vermeiden.

Warum nicht nur die klassische Art und Weise?

abstract class AbstractBase
{
    protected string _Description = "I am boring abstract default value";
}

class Foo : AbstractBase {

     public Foo() {
       _Description = "I am foo!";
     }
}

Es ist nicht statisch, wenn sie auf einer Instanz aufgerufen werden muss.

Wenn Sie sich nicht auf einer Instanz anrufen, dann gibt es keinen Polymorphismus im Spiel (das heißt ChildA.Description völlig unabhängig von ChildB.Description ist, soweit die betreffende Sprache ist).

Eine mögliche Abhilfe ist ein Singleton Ihrer abgeleiteten Klasse in Ihrer Basisklasse mit Hilfe von Generics zu definieren.

import System;

public abstract class AbstractBase<T>
    where T : AbstractBase<T>, new()
{
    private static T _instance = new T();

    public abstract string Description { get; }
    public static string GetDescription()
    {
        return _instance.Description;
    }
}

public class DerivedClass : AbstractBase<DerivedClass>
{
    public override string Description => "This is the derived Class";
}

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(DerivedClass.GetDescription());
        Console.ReadKey();
    }
}

Der Trick ist, Ihre AbstractBase<T> einige Details zu erzählen, wie DerivedClass implementiert:

  • Es ist newable mit where T: new() so eine Singleton-Instanz erstellen können
  • Es leitet sich von selbst mit where T : AbstractBase<T> so ist es, dass es weiß, wird eine Implementierung von Description sein

Auf diese Weise _instance enthält das Description Feld, das in der statischen Methode GetDescription() aufgerufen werden kann. Dies zwingt Sie Ihre Description zu überschreiben DerivedClassin und ermöglicht Ihnen, dessen Wert mit DerivedClass.GetDescription() anrufen

Sie könnten der „abstrakt“ Basismethode machen einen Exception werfen, so dann ein Entwickler „gewarnt“, wenn er versucht, diese Methode auf einer untergeordneten Klasse aufrufen, ohne zu überschreiben.

Der Nachteil ist, dass man könnte die Klasse erweitern und diese Methode nicht verwenden. beziehen sich dann auf andere Antworten zur Verfügung gestellt.

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