When creating classes, we need to ensure that the class prohibits any breaking modifications by needing to change internal code. We say that such a class is closed. If we need to change it somehow, we can do so by extending the class. This extensibility is where we say that the class is open for extensions.
You will create a class that determines the skills of a trooper by looking at the class of trooper. We will show you the way many developers create such a class and the way it can be created using the open/closed principle.
StarTrooper
:public class StarTrooper { }
TrooperClass
to identify the type of trooper we want to return the skills of. Also, create a List<string>
variable to contain the skills of the specific trooper class. Finally, create a method called GetSkills
that returns the specific set of skills for the given trooper class.The class is quite straightforward, but the implementation of the code is something we see a lot. Sometimes, instead of a switch
statement, you will see a whole lot of if
else
statements. While the functionality of the code is clear, it is not easy to add another class of trooper to the StarTrooper
class without changing code. Assume that you now have to add an additional Engineer
class to the StarTrooper
class. You would have to modify the TrooperClass
enumeration and the code in the switch
statement.
This changing of code can cause you to introduce bugs into code that was previously working fine. We now see that the StarTrooper
class is not closed and can't be extended easily to accommodate additional TrooperClass
objects:
public enum TrooperClass { Soldier, Medic, Scientist } List<string> TroopSkill; public List<string> GetSkills(TrooperClass troopClass) { switch (troopClass) { case TrooperClass.Soldier: return TroopSkill = new List<string>(new string[] { "Weaponry", "TacticalCombat", "HandToHandCombat" }); case TrooperClass.Medic: return TroopSkill = new List<string>(new string[] { "CPR", "AdvancedLifeSupport" }); case TrooperClass.Scientist: return TroopSkill = new List<string>(new string[] { "Chemistry", "MollecularDeconstruction", "QuarkTheory" }); default: return TroopSkill = new List<string>(new string[] { "none" }); } }
StarTrooper
class and create a Trooper
class. The GetSkills
method is declared as virtual
:public class Trooper { public virtual List<string> GetSkills() { return new List<string>(new string[] { "none" }); } }
Soldier
, Medic
, and Scientist
trooper classes available. Create the following derived classes that inherit from the Trooper
class. You can see that the override
keyword is used when creating the GetSkills
method:public class Soldier : Trooper { public override List<string> GetSkills() { return new List<string>(new string[] { "Weaponry", "TacticalCombat", "HandToHandCombat" }); } } public class Medic : Trooper { public override List<string> GetSkills() { return new List<string>(new string[] { "CPR", "AdvancedLifeSupport" }); } } public class Scientist : Trooper { public override List<string> GetSkills() { return new List<string>(new string[] { "Chemistry", "MollecularDeconstruction", "QuarkTheory" }); } }
Trooper
. If we now want to add the Engineer
class, we would simply override the GetSkills
method after inheriting from the Trooper
class created earlier:public class Engineer : Trooper { public override List<string> GetSkills() { return new List<string>(new string[] { "Construction", "Demolition" }); } }
The classes derived from the Trooper
class are extensions of the Trooper
class. We can say that each class is closed, because modifying it does not necessitate changing the original code. The Trooper
class is also extensible because we have been able to easily extend the class by creating derived classes from it.
Another by-product of this design is smaller, more manageable code that is easier to read and understand.
18.117.77.158