我知道这有点违反枚举的想法,但是可以在C#/ Java中扩展枚举吗?我的意思是“扩展”,既是向枚举添加新值,也就是从现有枚举继承的OO。
我认为这在Java中是不可能的,因为它是最近才得到的(Java 5?)。但是,C#对于希望做疯狂事情的人似乎更宽容,所以我认为这可能是有可能的。大概可以通过反思来破解它(不是每个人都实际使用该方法)?
我不一定对实现任何给定的方法感兴趣,它只是在引起我好奇时才引起我的好奇:-)
Answers:
您不能扩展Enums的原因是,它将导致多态性问题。
假设您有一个枚举MyEnum,其值分别为A,B和C,并将其值D扩展为MyExtEnum。
假设某个方法在某处期望myEnum值,例如作为参数。提供MyExtEnum值应该是合法的,因为它是子类型,但是现在当值变成D时您将要做什么?
为了消除此问题,扩展枚举是非法的
switch提供枚举值而不提供default大小写或引发异常。而且,即使这样做,运行时枚举也可能来自单独的编译
default大小写。
switch来提供所需的值时,例如本地的return
DayOfWeek a = (DayOfWeek) 1; DayOfWeek b = (DayOfWeek) 4711; Console.WriteLine(a + ", " + b);
当内置枚举还不够时,您可以按照旧的方式进行操作,然后自己制作。例如,如果您想添加其他属性,例如描述字段,则可以按照以下步骤进行操作:
public class Action {
public string Name {get; private set;}
public string Description {get; private set;}
private Action(string name, string description) {
Name = name;
Description = description;
}
public static Action DoIt = new Action("Do it", "This does things");
public static Action StopIt = new Action("Stop It", "This stops things");
}
然后,您可以将其像枚举一样对待:
public void ProcessAction(Action a) {
Console.WriteLine("Performing action: " + a.Name)
if (a == Action.DoIt) {
// ... and so on
}
}
诀窍是确保构造函数是私有的(如果要继承则受保护),并且实例是静态的。
final到public static Action DoIt = new Action("Do it", "This does things");线,而不是类。
readonly,ala:public static readonly Action DoIt = new Action("Do it", "This does things");
您走错了路:枚举的子类将具有较少的条目。
用伪代码考虑:
enum Animal { Mosquito, Dog, Cat };
enum Mammal : Animal { Dog, Cat }; // (not valid C#)
任何可以接受动物的方法都应该能够接受哺乳动物,但不能接受。子类化是为了使某些内容更具体而不是更一般。这就是为什么“对象”是类层次结构的根源。同样,如果枚举是可继承的,则枚举层次结构的假想根将具有所有可能的符号。
但是不,C#/ Java不允许使用子枚举AFAICT,尽管有时它确实很有用。可能是因为他们选择将Enums实现为int类型(如C)而不是内部符号(如Lisp)。(以上,(动物)1代表什么,(哺乳动物)1代表什么,它们的值相同吗?)
不过,您可以编写自己的类似枚举的类(使用其他名称)。使用C#属性,它甚至看起来还不错。
枚举应该代表所有可能值的枚举,因此扩展而不是违背了这一思想。
但是,在Java(可能是C ++ 0x)中可以执行的是使用接口而不是枚举类。然后,将标准值放入实现该功能的枚举中。显然,您不会使用java.util.EnumSet之类的东西。这是“更多NIO功能”中采用的方法,应该在JDK7中使用。
public interface Result {
String name();
String toString();
}
public enum StandardResults implements Result {
TRUE, FALSE
}
public enum WTFResults implements Result {
FILE_NOT_FOUND
}
如果您的意思是在基类的意义上扩展,那么在Java中……不。
但是,如果这就是您的意思,则可以扩展枚举值以具有属性和方法。
例如,以下代码使用Bracket枚举:
class Person {
enum Bracket {
Low(0, 12000),
Middle(12000, 60000),
Upper(60000, 100000);
private final int low;
private final int high;
Brackets(int low, int high) {
this.low = low;
this.high = high;
}
public int getLow() {
return low;
}
public int getHigh() {
return high;
}
public boolean isWithin(int value) {
return value >= low && value <= high;
}
public String toString() {
return "Bracket " + low + " to " + high;
}
}
private Bracket bracket;
private String name;
public Person(String name, Bracket bracket) {
this.bracket = bracket;
this.name = name;
}
public String toString() {
return name + " in " + bracket;
}
}
不久以前就看到了有关Java的帖子,请访问http://www.javaspecialists.eu/archive/Issue161.html。
我希望能够将值添加到C#枚举中,这些值是现有值的组合。例如(这就是我想要做的):
AnchorStyles定义为
public enum AnchorStyles {
None = 0,
Top = 1,
Bottom = 2,
Left = 4,
Right = 8,
}
我想添加一个AnchorStyles.BottomRight = Right + Bottom,所以不用说
my_ctrl.Anchor = AnchorStyles.Right | AnchorStyles.Bottom;
我可以说
my_ctrl.Anchor = AnchorStyles.BottomRight;
这不会引起上面提到的任何问题,因此,如果可能的话,会很好。
不久前,我什至想做这样的事情,发现枚举扩展会破坏很多基本概念……(不仅仅是polymorphisim)
但是,如果在外部库中声明了枚举,您仍然可能需要做,并且请记住,使用此枚举扩展时应格外小心。
public enum MyEnum { A = 1, B = 2, C = 4 }
public const MyEnum D = (MyEnum)(8);
public const MyEnum E = (MyEnum)(16);
func1{
MyEnum EnumValue = D;
switch (EnumValue){
case D: break;
case E: break;
case MyEnum.A: break;
case MyEnum.B: break;
}
}
就Java而言,这是不允许的,因为将元素添加到枚举将有效地创建超类而不是子类。
考虑:
enum Person (JOHN SAM}
enum Student extends Person {HARVEY ROSS}
多态的一般用例是
Person person = Student.ROSS; //not legal
这显然是错误的。