Ich weiß, dass dies eher gegen die Idee von Aufzählungen verstößt, aber ist es möglich, Aufzählungen in C # / Java zu erweitern? Ich meine "erweitern" sowohl im Sinne des Hinzufügens neuer Werte zu einer Aufzählung als auch im Sinne des Erbens von einer vorhandenen Aufzählung.
Ich gehe davon aus, dass dies in Java nicht möglich ist, da es sie erst vor relativ kurzer Zeit erhalten hat (Java 5?). C # scheint jedoch eher verzeihend für Leute zu sein, die verrückte Dinge tun wollen, also dachte ich, dass es irgendwie möglich sein könnte. Vermutlich könnte es durch Reflexion gehackt werden (nicht, dass Sie alle diese Methode tatsächlich anwenden würden)?
Ich bin nicht unbedingt daran interessiert, eine bestimmte Methode zu implementieren, sie hat nur meine Neugier geweckt, als sie mir einfiel :-)
Antworten:
Der Grund, warum Sie Enums nicht erweitern können, liegt darin, dass dies zu Problemen mit dem Polymorphismus führen würde.
Angenommen, Sie haben eine Aufzählung MyEnum mit den Werten A, B und C und erweitern sie mit dem Wert D als MyExtEnum.
Angenommen, eine Methode erwartet irgendwo einen myEnum-Wert, beispielsweise als Parameter. Es sollte legal sein, einen MyExtEnum-Wert anzugeben, da es sich um einen Subtyp handelt. Was werden Sie nun tun, wenn sich herausstellt, dass der Wert D ist?
Um dieses Problem zu beheben, ist das Erweitern von Aufzählungen illegal
quelle
switch
Enum-Werte zu, ohne einendefault
Fall anzugeben oder eine Ausnahme auszulösen. Und selbst wenn dies der Fall wäre, könnte die Aufzählung zur Laufzeit aus einer separaten Zusammenstellung stammendefault
Fall oder Werfen einschalten .switch
, um einen erforderlichen Wert anzugeben, z. B. die Initiale eines lokalen oder anreturn
DayOfWeek a = (DayOfWeek) 1; DayOfWeek b = (DayOfWeek) 4711; Console.WriteLine(a + ", " + b);
Wenn eingebaute Aufzählungen nicht ausreichen, können Sie dies auf die altmodische Weise tun und Ihre eigenen erstellen. Wenn Sie beispielsweise eine zusätzliche Eigenschaft hinzufügen möchten, z. B. ein Beschreibungsfeld, können Sie dies wie folgt tun:
Sie können es dann wie eine Aufzählung behandeln:
Der Trick besteht darin, sicherzustellen, dass der Konstruktor privat ist (oder geschützt ist, wenn Sie erben möchten) und dass Ihre Instanzen statisch sind.
quelle
final
zurpublic static Action DoIt = new Action("Do it", "This does things");
Zeile als zur Klasse.readonly
, ala:public static readonly Action DoIt = new Action("Do it", "This does things");
Sie gehen den falschen Weg: Eine Unterklasse einer Aufzählung hätte weniger Einträge.
Denken Sie im Pseudocode:
Jede Methode, die ein Tier aufnehmen kann, sollte ein Säugetier aufnehmen können, aber nicht umgekehrt. Unterklassen dienen dazu, etwas spezifischer und nicht allgemeiner zu machen. Deshalb ist "Objekt" die Wurzel der Klassenhierarchie. Wenn Aufzählungen vererbbar wären, hätte eine hypothetische Wurzel der Aufzählungshierarchie jedes mögliche Symbol.
Aber nein, C # / Java erlaubt keine Unteraufzählungen, AFAICT, obwohl es manchmal wirklich nützlich wäre. Dies liegt wahrscheinlich daran, dass Enums als Ints (wie C) anstelle von internen Symbolen (wie Lisp) implementiert wurden. (Was repräsentiert (Tier) 1 oben und was repräsentiert (Säugetier) 1 und haben sie den gleichen Wert?)
Sie könnten jedoch Ihre eigene enumähnliche Klasse (mit einem anderen Namen) schreiben, die dies vorsieht. Mit C # -Attributen sieht es vielleicht sogar gut aus.
quelle
Aufzählungen sollen die Aufzählung aller möglichen Werte darstellen, daher widerspricht das Erweitern eher der Idee.
In Java (und vermutlich in C ++ 0x) können Sie jedoch eine Schnittstelle anstelle einer Enum-Klasse verwenden. Fügen Sie dann Standardwerte in eine Aufzählung ein, die die Funktion implementiert. Offensichtlich können Sie java.util.EnumSet und dergleichen nicht verwenden. Dies ist der Ansatz, der in "mehr NIO-Funktionen" verfolgt wird, die in JDK7 enthalten sein sollten.
quelle
Sie können .NET Reflection verwenden, um die Beschriftungen und Werte zur Laufzeit aus einer vorhandenen Enumeration abzurufen (
Enum.GetNames()
undEnum.GetValues()
sind die beiden spezifischen Methoden, die Sie verwenden würden), und dann mithilfe der Code-Injection eine neue mit diesen und einigen neuen Elementen erstellen. Dies scheint etwas analog zu "Erben von einer bestehenden Aufzählung".quelle
Das Hinzufügen von Aufzählungen ist ziemlich häufig, wenn Sie zum Quellcode zurückkehren und ihn bearbeiten. Eine andere Methode (Vererbung oder Reflexion, falls möglich) wird Sie wahrscheinlich wieder treffen, wenn Sie ein Upgrade der Bibliothek und erhalten Sie haben den gleichen Aufzählungsnamen oder den gleichen Aufzählungswert eingeführt. Ich habe viel Code auf niedriger Ebene gesehen, bei dem die Ganzzahl mit der Binärcodierung übereinstimmt, bei der Probleme auftreten würden
Im Idealfall sollten Code-Referenzierungs-Enums nur als gleich (oder als Schalter) geschrieben werden. Versuchen Sie, zukunftssicher zu sein, indem Sie nicht erwarten, dass der Enum-Satz const ist
quelle
Wenn Sie meinen, erstreckt sich im Sinne der Basisklasse, dann in Java ... nein.
Sie können einen Aufzählungswert jedoch um Eigenschaften und Methoden erweitern, wenn Sie dies meinen.
Im Folgenden wird beispielsweise eine Bracket-Aufzählung verwendet:
quelle
Ich habe niemanden gesehen, der dies erwähnte, aber der Ordnungswert einer Aufzählung ist wichtig. Bei Grails wird beispielsweise beim Speichern einer Aufzählung in der Datenbank der Ordnungswert verwendet. Wenn Sie eine Aufzählung irgendwie erweitern könnten, was wären die Ordnungswerte Ihrer Erweiterungen? Wenn Sie es an mehreren Stellen erweitern würden, wie könnten Sie eine Art Ordnung für diese Ordnungszahlen bewahren? Chaos / Instabilität in den Ordnungswerten wäre eine schlechte Sache, was wahrscheinlich ein weiterer Grund ist, warum die Sprachdesigner dies nicht berührt haben.
Eine weitere Schwierigkeit, wenn Sie der Sprachdesigner waren, wie können Sie die Funktionalität der values () -Methode beibehalten, die alle Enum-Werte zurückgeben soll. Worauf würden Sie sich berufen und wie würden alle Werte erfasst?
quelle
Ich habe vor einiger Zeit einen diesbezüglichen Beitrag für Java gesehen, siehe http://www.javaspecialists.eu/archive/Issue161.html .
quelle
Sie können keine Aufzählung erben oder erweitern. Sie können Attribute verwenden , um eine Beschreibung zu deklarieren . Wenn Sie nach einem ganzzahligen Wert suchen, ist dieser integriert.
quelle
Hmmm - soweit ich weiß, ist dies nicht möglich - Aufzählungen werden zur Entwurfszeit geschrieben und dienen dem Programmierer als Annehmlichkeit.
Ich bin mir ziemlich sicher, dass beim Kompilieren des Codes die Namen in Ihrer Aufzählung durch die entsprechenden Werte ersetzt werden, wodurch das Konzept einer Aufzählung und (daher) die Möglichkeit, sie zu erweitern, entfernt werden.
quelle
Ich möchte in der Lage sein, C # -Aufzählungen, die Kombinationen vorhandener Werte sind, Werte hinzuzufügen. Zum Beispiel (das ist, was ich tun möchte):
AnchorStyles ist definiert als
public enum AnchorStyles { None = 0, Top = 1, Bottom = 2, Left = 4, Right = 8, }
und ich möchte einen AnchorStyles.BottomRight = Right + Bottom hinzufügen, anstatt zu sagen
Ich kann nur sagen
Dies verursacht keine der oben genannten Probleme, daher wäre es schön, wenn es möglich wäre.
quelle
Vor einiger Zeit wollte sogar ich so etwas machen und stellte fest, dass Enum-Erweiterungen viele grundlegende Konzepte zunichte machen würden ... (Nicht nur Polymorphisim)
Möglicherweise müssen Sie dies dennoch tun, wenn die Aufzählung in einer externen Bibliothek deklariert ist. Denken Sie daran, dass Sie bei der Verwendung dieser Aufzählungserweiterungen besondere Vorsicht walten lassen sollten ...
quelle
In Bezug auf Java ist dies nicht zulässig, da das Hinzufügen von Elementen zu einer Aufzählung effektiv eine Superklasse anstelle einer Unterklasse erstellen würde.
Erwägen:
Ein allgemeiner Anwendungsfall des Polymorphismus wäre
das ist eindeutig falsch.
quelle
Eine vorübergehende / lokale Problemumgehung , wenn Sie nur eine sehr lokale / einmalige Verwendung wünschen:
Alle Antworten finden Sie unter: Enum "Inheritance"
quelle