【问题标题】:Using enums or a set of classes when I know I have a finite set of different options?当我知道我有一组有限的不同选项时,使用枚举或一组类?
【发布时间】:2010-04-08 16:20:22
【问题描述】:

假设我定义了以下类:

public abstract class Event {
    public DateTime Time { get; protected set; }

    protected Event(DateTime time) {
        Time = time;
    }
}

这之间你更喜欢什么:

public class AsleepEvent : Event {
    public AsleepEvent(DateTime time) : base(time) { }
}

public class AwakeEvent : Event {
    public AwakeEvent(DateTime time) : base(time) { }
}

还有这个:

public enum StateEventType {
    NowAwake,
    NowAsleep
}    

public class StateEvent : Event {
    protected StateEventType stateType;

    public StateEvent(DateTime time, StateEventType stateType) : base(time) {
        stateType = stateType;
    }
}

为什么?我通常更倾向于第一种选择,但我无法解释为什么。它是完全一样的还是使用一个而不是另一个有什么优势?也许使用第一种方法更容易添加更多“状态”,尽管在这种情况下我 100% 确定我只想要两种状态:现在醒着,现在睡着了(它们表示一个人醒来和一个人睡着的时刻)。

【问题讨论】:

    标签: c# java inheritance oop enums


    【解决方案1】:

    我更喜欢第一个。您可以将方法和行为附加到类,并从枚举常见的 switch/case 模式转向真正的多态性(以及维护方面的好处 - 添加新案例等)。

    【讨论】:

      【解决方案2】:

      真正的面向对象不使用if!比条件更喜欢多态性。

      当然,在某些情况下,enum 是可行的方法(例如,如果您有非常非常多的状态,或者您知道对于域,很可能所有观察者都会感兴趣在所有转换中),但在一般情况下,第一个选项不太复杂。使用第二种方法,每个侦听器都必须重复同一段代码:

      if (theStateImInterestedIn == event.stateType){ 
          /* actual code */ 
      }
      

      并且每个 监听器都需要这个,除了对所有 转换以相同方式反应的监听器!代码重复!啊啊啊!众所周知,重复的代码会导致错误(因此DRY principle),因此我们可以得出结论,您的直觉是正确的 - 第一个选项(使用两个不同的类)更好,因为每个单独的侦听器实现都会更少样板。

      还有;在那里添加一个else,当你添加一个新状态时,你会遇到有趣的事情:一些听众对这两种类型的事件都感兴趣,因此假设else分支意味着“我没有的状态” t 检查if"。它们现在中断了,因为 else 子句涵盖 >1 个状态。

      【讨论】:

        【解决方案3】:

        这取决于你在做什么。如果您只管理状态,那么我会说坚持使用 Enums(这就是我要做的)。如果您的状态不仅仅是状态,如果它们的实例具有行为,那么请使用类。

        【讨论】:

        • 每种状态(醒着或睡着)会有不同的行为。
        • @devoured elysium:啊,那么它们不仅仅是简单的状态。如果这些“状态”将被设置并“做事”,那么使用基于类的解决方案可能比枚举更好。
        【解决方案4】:

        绝对是第一种方式。需求总是变化的。 第一种方式也更加简洁——您可以在任何地方使用基类型,因此不会暴露任何派生类型——多态性是最好的。

        【讨论】:

          【解决方案5】:

          第一个的缺点是你不能改变状态。如果一个对象需要从清醒状态进入睡眠状态,您需要创建一个新对象并复制信息等。很快它将无法正常工作。根据名称,我认为这种情况需要改变状态的行为。

          枚举的第二个选项将起作用,但它会导致基于状态的 if/switch 语句,正如其他海报所指出的那样。当您重复相同类型的 switch/if 语句时(如果不是问题,重复的 if 是问题),最好转向多态解决方案。在这种情况下,您可以将枚举替换为接口或抽象类,并拥有尽可能多的实现。将进入 switch/if 语句的行为将进入具体实现中的方法

          【讨论】:

          • 忘了说这个,对象创建后我不需要改变状态。
          • 我被类名弄糊涂了。我,我自己,偶尔会从睡眠状态变为清醒状态:)。对于没有状态变化的情况,如果有重复的基于状态的 if 语句,我也会投票给选项 1。
          猜你喜欢
          • 1970-01-01
          • 2023-03-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-08-21
          相关资源
          最近更新 更多