当前位置:  开发笔记 > 编程语言 > 正文

通过继承扩展枚举

如何解决《通过继承扩展枚举》经验,为你挑选了4个好方法。

我知道这反对了枚举的想法,但是有可能在C#/ Java中扩展枚举吗?我的意思是"扩展",无论是为枚举添加新值,还是从现有枚举继承的OO意义.

我认为它在Java中是不可能的,因为它最近才得到它们(Java 5?).C#似乎对想要做疯狂事情的​​人更宽容,所以我认为这可能是某种方式.据推测它可以通过反射来破解(不是你每次都使用那种方法)?

我不一定对实现任何给定的方法感兴趣,它只是在我遇到它时激起了我的好奇心:-)



1> Rik..:

你无法扩展枚举的原因是因为它会导致多态性问题.

假设您有一个包含值A,B和C的枚举MyEnum,并将其值D扩展为MyExtEnum.

假设某个方法需要myEnum值,例如作为参数.提供MyExtEnum值应该是合法的,因为它是一个子类型,但是现在当它结果是D时你要做什么呢?

要消除此问题,扩展枚举是非法的


实际上,原因很简单,它没有任何意义.您提到的问题,即客户端代码接收它不期望的常量,仍然存在于当前实现中 - 实际上编译器不允许您在没有提供"默认"情况或抛出的情况下"切换"枚举值.例外.而且,即使它确实如此,运行时的枚举也可以来自单独的编译
这不是个人的,Rik.但这几乎是有史以来最糟糕的原因!多态性和枚举..."DayOfWeek a =(DayOfWeek)1; DayOfWeek b =(DayOfWeek)4711; Console.WriteLine(a +","+ b);`

2> tsimon..:

当内置枚举不够时,你可以用旧时尚的方式来制作你自己的.例如,如果要添加其他属性(例如,描述字段),则可以按如下方式执行:

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
    }
}

诀窍是确保构造函数是私有的(如果你想继承,则保护),并且你的实例是静态的.


@alastairs我认为他的意思是将`final`添加到`public static Action DoIt = new Action("Do it","This does things");`line,而不是类.

3> 小智..:

你的方法是错误的:枚举的子类会有更少的条目.

在伪代码中,想一想:

enum Animal { Mosquito, Dog, Cat };
enum Mammal : Animal { Dog, Cat };  // (not valid C#)

任何可以接受动物的方法应该能够接受哺乳动物,但不能相反.子类化是为了使某些更具体,而不是更一般.这就是为什么"对象"是类层次结构的根.同样,如果枚举是可继承的,那么枚举层次结构的假设根将具有所有可能的符号.

但不,C#/ Java不允许子枚举,AFAICT,尽管它有时会非常有用.这可能是因为他们选择将Enums实现为int(如C)而不是实体符号(如Lisp).(上面,(动物)1代表什么,(哺乳动物)1代表什么,它们是相同的值?)

不过,您可以编写自己的类似枚举的类(使用不同的名称).使用C#属性,它甚至可能看起来很好.


@Kieveli,你的分析是错误的.添加成员对对象的影响与添加其可能值集不同.这不是肯组成的; 有明确而精确的计算机科学规则可以解释为什么它以这种方式运作.尝试搜索协方差和逆变(不仅仅是学术手淫,它还可以帮助您理解功能签名和容器等规则).
有趣的分析.从来没有想过这样!

4> Tom Hawtin -..:

枚举应该代表所有可能值的枚举,因此扩展反而违背了这个想法.

但是,你可以用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
}

推荐阅读
mobiledu2402851203
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有