Using enumerations or a set of classes, when I know, do I have a finite set of different options?

Let's say I defined the following class:

public abstract class Event { public DateTime Time { get; protected set; } protected Event(DateTime time) { Time = time; } } 

Which would you prefer between this:

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

and this:

 public enum StateEventType { NowAwake, NowAsleep } public class StateEvent : Event { protected StateEventType stateType; public StateEvent(DateTime time, StateEventType stateType) : base(time) { stateType = stateType; } } 

and why? I am generally more inclined to the first option, but I can not explain why. Is it absolutely the same or are there any advantages to using one instead of the other? Perhaps with the first method it is easier to add more "states", although in this case I am 100% sure that I need only two states: now I am awake and now sleeps (they signal the moments when one wakes up and one falls asleep).

+4
source share
5 answers

I prefer the first one. You can attach methods and behavior to classes and move away from the switch / case pattern, common with enumerations, to true polymorphism (and its service benefits - adding new cases, etc.).

+6
source

Real OOPers do not use if ! Prefer polymorphism to conventions.

Of course, there may be situations where enum is the way to go (say, if you have very, very many states or you know that it is very likely for a domain that all observers will be interested in all transitions), but in the general case the first option is less complicated . Using the second approach, each listener must repeat the same piece of code:

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

And each listener needs this, except for listeners who also respond to all transitions! Code duplication! Aaaaargh! As we all know, the repeated code causes errors (hence the DRY principle ), and therefore we can conclude that your gut feeling is correct - the first option (using two different classes) is better, since each individual implementation of the receiver will have a smaller boiler plate.

Also; add else , and you have interesting moments when you add a new state: some listeners were interested in both types of events and therefore assumed that the else branch means "state in which I did not check in if ". Now they are broken because the else clause spans state> 1.

+3
source

It depends on what you do. If you only manage states, then I would say that I stick to Enums (this is what I will do). If your states are more than just states, if their instances will have behavior, then go to classes.

+2
source

Definitely the first way. Requirements are always changing. In addition, this is a much, much cleaner first way - you can use the base type everywhere and thus not expose any of the derivatives - the polymorphism in it is the best.

+2
source

The disadvantage of the first is that you cannot change state. If an object needs to switch from a standby state to a sleep state, you need to create a new object and copy information, etc. It will not work soon. Based on the names, I think that in this case a change in the state of behavior is required.

The second option with enumeration will work, but this will lead to the fact that if / switch statements are state-based, as other posters note. At that moment when you repeat the same switch / if statement (ifs is not a problem, repeating ifs is a problem), it is better to switch to a polymorphic solution. In this case, you should replace enum with an interface or an abstract class and have as many implementations as you want. Behavior that gets into switch / if statements will go into methods in specific implementations

+1
source

Source: https://habr.com/ru/post/1306378/


All Articles