Polymorphism in Action

  1#include <iostream>
  2#include <string>
  3#include <vector>
  4
  5// Base interface class to enable polymorphism
  6class IBase {
  7public:
  8  virtual ~IBase() =
  9      default; // Virtual destructor to ensure proper cleanup of derived classes
 10  virtual void status() const = 0; // Pure virtual function to enforce
 11                                   // implementation in derived classes
 12};
 13
 14// ISwitchable Interface, represents an object that can be turned on and off
 15class ISwitchable : virtual public IBase {
 16public:
 17  virtual ~ISwitchable() = default; // Virtual destructor
 18  virtual void turnOn() = 0;  // Pure virtual function to turn on the object
 19  virtual void turnOff() = 0; // Pure virtual function to turn off the object
 20  virtual bool
 21  isOn() const = 0; // Pure virtual function to check if the object is on
 22
 23  // Provides status indicating whether the switch is on or off
 24  void status() const override {
 25    if (isOn())
 26      std::cout << "Switch is On" << std::endl;
 27    else
 28      std::cout << "Switch is Off" << std::endl;
 29  }
 30};
 31
 32// IDimmable Interface, represents an object that can adjust brightness
 33class IDimmable : virtual public IBase {
 34public:
 35  virtual ~IDimmable() = default;            // Virtual destructor
 36  virtual void setBrightness(int level) = 0; // Set the brightness level
 37  virtual int getBrightness() const = 0;     // Get the brightness level
 38
 39  // Provides status indicating the brightness level
 40  void status() const override {
 41    std::cout << "Brightness is: " << getBrightness() << std::endl;
 42  }
 43};
 44
 45// IAdjustableTemperature Interface, represents an object that can adjust
 46// temperature
 47class IAdjustableTemperature : virtual public IBase {
 48public:
 49  virtual ~IAdjustableTemperature() = default; // Virtual destructor
 50  virtual void setTemperature(int temp) = 0;   // Set the temperature
 51  virtual int getTemperature() const = 0;      // Get the current temperature
 52
 53  // Provides status indicating the temperature level
 54  void status() const override {
 55    std::cout << "Temperature is: " << getTemperature() << std::endl;
 56  }
 57};
 58
 59// LightBulb class implementing ISwitchable interface
 60class LightBulb : public ISwitchable {
 61private:
 62  bool on;        // Tracks if the bulb is on
 63  int brightness; // Tracks brightness level (though unused here)
 64
 65public:
 66  LightBulb()
 67      : on(false), brightness(0) {
 68  } // Constructor initializes bulb as off and brightness to 0
 69
 70  void turnOn() override { on = true; }     // Turn the bulb on
 71  void turnOff() override { on = false; }   // Turn the bulb off
 72  bool isOn() const override { return on; } // Check if the bulb is on
 73
 74  void status() const override {
 75    ISwitchable::status();
 76  } // Output the on/off status of the bulb
 77};
 78
 79// DimmableBulb class implementing both ISwitchable and IDimmable interfaces
 80class DimmableBulb : public ISwitchable, public IDimmable {
 81private:
 82  bool on;        // Tracks if the bulb is on
 83  int brightness; // Tracks brightness level
 84
 85public:
 86  DimmableBulb()
 87      : on(false), brightness(0) {} // Initialize bulb as off with brightness 0
 88
 89  void turnOn() override { on = true; }     // Turn the bulb on
 90  void turnOff() override { on = false; }   // Turn the bulb off
 91  bool isOn() const override { return on; } // Check if the bulb is on
 92
 93  // Set brightness level, ensuring it stays between 0 and 100
 94  void setBrightness(int level) override {
 95    if (level < 0) {
 96      brightness = 0;
 97    } else if (level > 100) {
 98      brightness = 100;
 99    } else {
100      brightness = level;
101    }
102  }
103
104  int getBrightness() const override {
105    return brightness;
106  } // Get the current brightness level
107
108  // Print both switch and brightness statuses
109  void status() const override {
110    ISwitchable::status();
111    IDimmable::status();
112  }
113};
114
115// Thermostat class implementing ISwitchable and IAdjustableTemperature
116// interfaces
117class Thermostat : public ISwitchable, public IAdjustableTemperature {
118private:
119  bool on;         // Tracks if the thermostat is on
120  int temperature; // Tracks temperature level
121
122public:
123  Thermostat()
124      : on(false), temperature(20) {
125  } // Initialize thermostat as off with default temperature 20
126
127  void turnOn() override { on = true; }     // Turn the thermostat on
128  void turnOff() override { on = false; }   // Turn the thermostat off
129  bool isOn() const override { return on; } // Check if the thermostat is on
130
131  void setTemperature(int temp) override {
132    temperature = temp;
133  } // Set the desired temperature
134  int getTemperature() const override {
135    return temperature;
136  } // Get the current temperature
137
138  // Print both switch and temperature statuses
139  void status() const override {
140    ISwitchable::status();
141    IAdjustableTemperature::status();
142  }
143};
144
145// Fan class implementing ISwitchable interface
146class Fan : public ISwitchable {
147private:
148  bool on; // Tracks if the fan is on
149
150public:
151  Fan() : on(false) {} // Initialize fan as off
152
153  void turnOn() override { on = true; }     // Turn the fan on
154  void turnOff() override { on = false; }   // Turn the fan off
155  bool isOn() const override { return on; } // Check if the fan is on
156};
157
158// Main function to demonstrate the system
159int main() {
160  // Create instances of each device
161  LightBulb bulb;
162  DimmableBulb dimBulb;
163  Thermostat thermostat;
164  Fan fan;
165
166  // Polymorphic collection of all devices
167  std::vector<IBase *> allItems;
168  allItems.push_back(&bulb);
169  allItems.push_back(&dimBulb);
170  allItems.push_back(&thermostat);
171  allItems.push_back(&fan);
172
173  // Separate lists of devices by interface type
174  std::vector<ISwitchable *> switchables;
175  std::vector<IAdjustableTemperature *> tempAdjustables;
176  std::vector<IDimmable *> dimmables;
177
178  // Populate interface-specific vectors using dynamic casting
179  for (IBase *item : allItems) {
180    if (auto switchable = dynamic_cast<ISwitchable *>(item)) {
181      switchables.push_back(switchable);
182    }
183    if (auto dimmable = dynamic_cast<IDimmable *>(item)) {
184      dimmables.push_back(dimmable);
185    }
186    if (auto tempAdjustable = dynamic_cast<IAdjustableTemperature *>(item)) {
187      tempAdjustables.push_back(tempAdjustable);
188    }
189  }
190
191  // Max out brightness on all dimmable devices
192  for (auto &dimmable : dimmables)
193    dimmable->setBrightness(100);
194
195  // Set all adjustable temperature devices to 70 degrees
196  for (auto &tempAdjustable : tempAdjustables)
197    tempAdjustable->setTemperature(70);
198
199  // Turn on all switchable devices
200  for (auto &switchable : switchables)
201    switchable->turnOn();
202
203  // Print status of all devices
204  std::cout << "All Statuses:" << std::endl;
205  for (auto &item : allItems)
206    item->status();
207}