Chapter 13. Advanced OOP – Inheritance and Polymorphism

In this chapter, we will further extend our knowledge of OOP by looking at the slightly more advanced concepts of inheritance and polymorphism. We will then be able to use this new knowledge to implement the star characters of our game, Thomas and Bob. Here is what we will cover in this chapter in a little more detail:

  • How to extend and modify a class using inheritance?
  • Treating an object of a class as if it is more than one type of class by using polymorphism
  • Abstract classes and how designing classes that are never instantiated can actually be useful
  • Building an abstract PlayableCharacter class
  • Puting inheritance to work with Thomas and Bob classes
  • Adding Thomas and Bob to the game project

Inheritance

We have seen how we can use other people's hard work by instantiating/creating objects from the classes of the SFML library. But this whole OOP thing goes even further than that.

What if there is a class that has loads of useful functionality in it, but is not quite what we want? In this situation we can inherit from the other class. Just like it sounds, inheritance means we can harness all the features and benefits of other people's classes, including the encapsulation, while further refining or extending the code specifically to our situation. In this project, we will inherit from and extend some SFML classes. We will also do so with our own classes.

Let's look at some code that uses inheritance,

Extending a class

With all this in mind, let's look at an example class and see how we can extend it, just to see the syntax and as a first step.

First, we define a class to inherit from. This is no different from how we created any of our other classes. Take a look at this hypothetical Soldier class declaration:

class Soldier 
{ 
   private: 
      // How much damage can the soldier take 
      int m_Health; 
      int m_Armour; 
      int m_Range; 
      int m_ShotPower; 
       
    
   Public: 
      void setHealth(int h); 
      void setArmour(int a);   
      void setRange(int r); 
      void setShotPower(int p); 
}; 

In the previous code, we define a Soldier class. It has four private variables, m_Health, m_Armour, m_Range, and m_ShotPower. It has four public functions setHealth, setArmour, setRange, and setShotPower. We don't need to see the definition of the functions, they will simply initialize the appropriate variable that their name makes obvious.

We can also imagine that a fully implemented Soldier class would be much more in-depth than this. It would probably have functions such as shoot, goProne, and others. If we implemented a Soldier class in an SFML project, it would likely have a Sprite object, as well as an update and a getPostion function.

The simple scenario presented here is suitable for learning about inheritance. Now let's look at something new, actually inheriting from the Soldier class. Look at this code, especially the highlighted part:

class Sniper : public Soldier 
{ 
public: 
   // A constructor specific to Sniper 
   Sniper::Sniper(); 
}; 

By adding the : public Soldier code to the Sniper class declaration, Sniper inherits from Soldier. But what does this mean, exactly? Sniper is a Soldier. It has all the variables and functions of Soldier. Inheritance is more than this, however.

Notice also that in the previous code, we declare a Sniper constructor. This constructor is unique to Sniper. We have not only inherited from Soldier, we have extended  Soldier. All the functionality (definitions) of the Soldier class are handled by the Soldier class, but the definition of the Sniper constructor must be handled by the Sniper class.

This is what the hypothetical Sniper constructor definition might look like:

// In Sniper.cpp 
Sniper::Sniper() 
{ 
   setHealth(10); 
   setArmour(10);  
   setRange(1000); 
   setShotPower(100); 
} 

We could go ahead and write a bunch of other classes that are an extension of the Soldier class, perhaps Commando and Infantryman. Each would have the exact same variables and functions, but each could also have a unique constructor that initializes those variables appropriate to the type of Soldier. Commando might have very high m_Health and m_ShotPower but really puny m_Range. Infantryman might be in between Commando and Sniper, with mediocre values for each variable.

Tip

As if OOP were not useful enough already, we can now model real-world objects, including their hierarchies. We achieve this by sub-classing, extending, and inheriting from other classes.

The terminology we might like to learn here is that the class that is extended from is the super-class, and the class that inherits from the super-class is the sub-class. We can also say parent and child class.

Tip

You might find yourself asking this question about inheritance: Why? The reason is something like this: we can write common code once; in the parent class, we can update that common code and all classes that inherit from it are also updated. Furthermore, a sub-class only gets to use public and protected instance variables and functions. So, designed properly, this also further enhances the goals of encapsulation.

Did you say protected? Yes. There is an access specifier for class variables and functions called protected. You can think of protected variables as being somewhere between public and private. Here is a quick summary of access specifiers, along with more details about the protected specifier:

  • Public variables and functions can be accessed and used by anyone.
  • Private variables and functions can only be accessed/used by the internal code of the class. This is good for encapsulation, and when we need to access/change private variables, we can provide public getter and setter functions (such as getSprite and so on). If we extend a class that has private variables and functions, that child class cannot directly access the private data of its parent.
  • Protected variables and functions are almost the same as private. They cannot be accessed/used directly by an instance of the class. However, they can be used directly by any class that extends the class they are declared in. So it is like they are private, except to child classes.

To fully understand what protected variables and functions are and how they can be useful, let's look at another topic first and then we can see them in action.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.218.93.169