Introduction
I was doing some research on the use of protected methods in the inheritance world and was quite impressed with its actual purpose. Let's explore why the protected methods are useful with an example below.
Let's say we have a Base Printer class which has a public instance method Print(). We have two derived classes namely BlackWhitePrinter and ColorPrinter. Based on the users choice I would like to do one of the below:
- Printer printerObj = new BlackWhitePrinter();
- printObj.Print();
- or
- Printer printerObj = new ColorPrinter();
- printObj.Print();
Assume that we implement a factory pattern in order to get the Printer object based on the user preference and we will call the Print method.
Our base Printer class will look like this:
- public class Printer
- {
- private string inputData;
- private string inkType;
- public void Print()
- {
- GetInputData();
- inkType = FillCatridge();
- PrintData();
- }
-
- private void GetInputData()
- {
- Console.WriteLine("Enter the data to be printed ");
- inputData = Console.ReadLine();
- }
-
- private void PrintData()
- {
- Console.WriteLine(inputData + " printed in " + inkType);
- }
- protected virtual string FillCatridge()
- {
- return "Default";
- }
- }
Note that we have followed a template pattern in the Print() method of the base class to specify the order of steps while printing.
- Get the input data to be printed from the user
- We are making use of the protected FillCatridge() method to inject the behavior of the Printer chosen by the user.
- We are actually doing the work of printing
Since we need to override only the behavior of filling the cartridge, our derived classes will now look very neat and simple, similar to below:
- public class BlackWhitePrinter : Printer
- {
- protected override string FillCatridge()
- {
- return "Black and White";
- }
- }
-
- public class ColorPrinter : Printer
- {
- protected override string FillCatridge()
- {
- return "Color";
- }
- }
Now, let's check the behaviour of our implementation...
- Printer blackWhite= new BlackWhitePrinter();
- Printer color= new ColorPrinter();
- blackWhite.Print();
- color.Print();
And our output will be:
- Enter the data to be printed
- Black white data
- Black white data printed in Black and White
- Enter the data to be printed
- colorful data
- colorful data printed in Color
Conclusion
- We have to choose protected methods when we want to inject one of the behaviors to the base implementation from the derived classes.
- We are hiding the FillCatridge method to any instance of the Printer/Its derived classes, at the same time allowing the polymorphism of the FillCatridge method in derived classes.
- This also avoids the repetition of the same flow in the derived classes. In future, if we need to add more functionality, for example, getting the mode of print Portable/Landscape from the user, we can introduce a single method in the base class and include it in the Print() method, by which we are eliminating code repetition in the child classes thus avoiding the testing efforts.
Hope this helps!!