C #, implementieren ‚static abstrakt‘ wie Methoden
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?
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 vonDescription
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 DerivedClass
in 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.