Having considered the notions of encapsulation and abstraction, we will, in the following episodes, consider a third fundamental notion in OOP: inheritance. Let's start with an example, and forget, for once, rectangles and other geometric shapes to concentrate on players of a game. Imagine that we would like to play a game that involves warriors, magicians, thieves, and the like. How would we represent this? We could imagine for one that we have a class for warriors, a class for thieves, a class for magicians, and so on. For a warrior we could imagine that we could have data members such as a name, an energy level, a certain lifespan, and certainly a weapon. As for methods, we could imagine that a warrior can meet other people. For a thief, he would also have a name, an energy level, a lifespan, and he can also meet other people, and even steal from them. As for the magician, he would also have a name, energy level, lifespan he could also meet others and he would maybe also have a wand instead of a weapon. We could also have witches kind of like magicians but who would have a stick as well as a wand. All these classes would have much duplicated code, and would be a waste of time to write all that, and most importantly, would be problematic for maintenance. Imagine that we do want a property lifespan anymore, and instead have life points, or that the energy level is not an "int" but a "double". Then we would have to revise all the classes that we made. There is definitely a better way than this! This is where the notion of inheritance comes in: inheritance solves this type of problem by grouping together data members and methods that are common to each class into what we will call a superclass. This class regroups characteristics that are enriched or specialized in its derived classes. In our class, the superclass would be a class Personnage (TN: = character) a generic character which would by the way solve one of the problems we had: the fact that we did not have a class Personnage. Anticipating a little, here is what we could do using inheritance, by grouping in the class Personnage the properties shared by the classes: name, energy, lifespan, as well as methods, for example "recontrer" (TN: = meet). So this superclass groups together the characteristics of these characters which would be inherited by the thief, the magician, etc. with each character having his own particularities, like a weapon for the warrior, a wand for the magician, or a method "voler" (TN: =to steal) for the thief. For the magician we could also have an extension, a 2nd inheritance so that a witch is a sort of magician, who would have a stick as well as a wand. So this is the purpose of inheritance in OOP. It represents an "is-a" relationship, and avoids that code be duplicated. Inheritance also enables specialized or enriched classes to be created. So a superclass is a class from which subclasses are derived. We also say that subclasses inherit and we draw an arrow in this direction. Subclasses inherit from superclasses, and subclasses are as a result extensions, either by adding data members or methods, or by specializing the inherited methods, making them extensions of the superclass. Before detailing this in an example, let's investigate what a inheritance relationship implicates. If a subclass C1 is derived from a class C or "inherits" from the class C, we will say that C1 "is a" C. that is to say, that the type is inherited. So for example, if I have a variable x, of type C, and a variable y of type C1, I can in fact put y in x, because a C1 y "is a" C. Moreover, the class C1 inherits from the set of data members and methods of C. When we say the set of data members and members, the constructors are not included, so they are not inherited. The data members of C are as a result available in C1 without having to redefine them. Finally, extra data members or methods can be added to C1, which is called enrichment, and methods inherited from C can also be redefined in C1, which is called specialization. Let's see all this in an example. Imagine we make a superclass Personnage, with 2 subclasses Guerrier and Voleur (TN: guerrier = warrior, voleur = thief). So we said that when a subclass C1, for example Guerrier, is created from a superclass C, so for example here Personnage the type is inherited. Actually Guerrier is also a character, which allows us to write the following code. Suppose that we have declared a variable p of type Personnage and a variable g of type Guerrier that we manipulate and for example we say that the character p is the warrior g. So we put the warrior g in the character p, which we are allowed to do because a warrior is a character. Of course, we can't do the contrary and write "g = p;" A generic character is not a warrior, because characters can also be thieves or magicians, and we cannot put a thief in a warrior, it doesn't have any meaning. So here, the relationship has a certain direction, it's the warrior who is a character. We can also imagine a function that displays a character, and we could display g, which is a warrior here and is passed as argument to the function "afficher" as a character, (the function "afficher" sees g as a character), but we can only do this because a warrior is a character. A 2nd aspect of inheritance: Guerrier will inherit, that is to say, receive, contain the set of data members and methods of Personnage. So for example, if Personnage had a name, an energy, a lifespan, and a method "rencontrer", and Guerrier inherited of the class Personnage, then in Guerrier we would also have an energy, a lifespan, without needing to redefine them, and also a method rencontrer, so we could do something like this. Suppose that here, with a Guerrier g and Voleur v, which are characters, g , of type Guerrier, will inherit the method rencontrer, which we could invoke, if this method is included in the public interface of Personnage, using a syntax "g.rencontrer(v);", here we pass the thief v as argument to the method rencontrer, but what is important here is to see that this method rencontrer is visible to g and can be called by g because Guerrier has inherited this method from Personnage. Likewise, if we had some method in Guerrier, we can directly use the data member energie like this in a method of Guerrier, supposing that energie is not private. So energie is inherited from Personnage in the class Guerrier without having to add any code. It's done automatically thanks to inheritance. The third and last aspect that we want to focus on is that even if the members of a class are inherited, and are accessible in the subclasses, we can always add data members and methods which is called enrichment, e.g. adding a data member "weapon" to the class Guerrier, and we can redefine methods called specialization, so for instance, we could redefine the method rencontrer of the class Voleur by saying that when a thief meets another person, he also steals, for example. Inheritance is a paramount notion in POO, because it enables the code to be organized to make it more comprehensible by elucidating structural and semantical relationships that exist among the classes, for example, that a warrior is a character, or that a witch is a type of magician. Inheritance also avoids writing large sections of code, called code redundancy. Be careful in how you use inheritance, to use it only in "is-a" relationships, e.g. a warrior is a character, but a warrior is not a weapon, we say a warrior "has a" weapon, and to represent a relationship of possession, we will use a notion from before: encapsulation. Therefore, to summarize, a warrior inherits from the class Personnage but will also have as encapsulated data member a weapon. We saw that a subclass enherits from a superclass, inherit means receive and possess the data members and methods of this superclass, except for constructors. This aspect is transitive, that is to say if we have a super-super-class from which a superclass is derived, then in the subclass, we will find all the members of these 2 classes. More concretely, if I have a super-super-class A, from which a superclass B is derived, from which a class C is derived, we will find in C the members found in B, but also those in A, because B inherits them from A, and so they are accessible in B. So in B, I have the data members and methods of A, and by transitivity, I also have in C, these same data members and methods of A. So in a concrete example, if we have for instance a class Personnage, from which a class Magicien is derived, and if we say a witch is a kind of magician, then the class Sorcier inherits from the class Magicien. At this point, in the class Sorcier, we will also have the data members for the name, energy, lifespan that were inherited along with the method rencontrer that were inherited in the magician class and inherited again in the class Sorcier and of course, Sorcier will also have the member baguette, inherited from Magicien. Thus we have something like this for inheritance, a progressive enrichment of each class, finally resulting in, if we draw all the relationships between the classes, an arborescent graph, a treelike organization, where we see the dependencies between classes, the "is-a" relationships, and the relationships of inheritance, of data members, methods, and also types, which we call as whole, a class hierarchy, with the most general class, Personnnage, at the top, and the most specialized classes on the bottom. To summarize, the inheritance relationship avoids duplicating code. Superclasses, resulting from using "is-a" relationships in programs, also called "parent classes" are more broad, grouping general aspects, and so from them are derived subclasses also called "child classes", that receive the set of data members and methods, as well as the type of the superclass that they depend on. Up to now, this notion of inheritance has been presented very conceptually and theoretically, but how do we implement it in a real program, and make a subclass inherit from a superclass? Let's start with a concrete example. Suppose, that we want to define a class Rectangle with a width largeur and a height hauteur, and which is also a FigureGeometrique. And this class of geometric shapes also has a position. So we would have the following inheritance diagram, a superclass "FigureGeometrique", with a data member "position", and a subclass "Rectangle", derived from "FigureGeometrique". A rectangle is a geometric shape, and so will have supplementary data members, besides the inherited data member position, such as largeur and hauteur that are defined in Rectangle. But how do I code all this? The syntax for a subclass to inherit from a superclass is simply to add the keyword "extends" and the name of the superclass, after the heading of the subclass, so we would have: "class Name_subclass extends Name_superclass", and then, as usual, the definition of the subclass, with the definition of data members and methods unique to that subclass. So for example, if I have a class Rectangle, that inherits from the class "FigureGeometrique", I would write the following: "class Rectangle extends FigureGeometrique" and write the definition of the class underneath with, for example, the 2 data members largeur and hauteur particular to the class. The only thing I need to add to the precedent class definition for it to inherit from "FigureGeometrique" is this section of the code. In the same way, if we come back to the example of warriors, that inherit from characters, we would have a class Personnage previously defined, and the way to derive the class Guerrier from Personnage is simply by specifying: "class Guerrier extends Personnage", followed by the specific definition of the class Guerrier, such as defining a data member for weapons. So this concludes this introduction to an important concept in OOP: inheritance. In the next episodes, we will continue to deepen our understanding of this concept from a practical point of view, in how it is implemented in real code.