Now you are acquainted with the fundamental notions in OOP of encapsulation, abstraction, and inheritance. Let's move on to another important concept: polymorphism. In general terms, polymorphism provides that the same code can automatically adapt itself to the type of the data to which it is applied. This is important because it allows code to be much more generic: it can be written the same way for different types of data. Note that this video is only a brief introduction to polymorphism. We will be able to come back to this concept in more detail in the episodes next week. Let's take up our introductive example to inheritance. Suppose that we have a hierarchy of characters and that we want to program a game where a group of different characters meet a central figure. How do we implement this? The idea is to have a group of characters that we could for example store in an array to simplify, a array of fixed size, and we want to ensure that these characters meet one by one the principle character. So we would program each encounter using a loop, so as to allow each character of the group to meet the principle character in turn. The main idea here is that in an array of characters, we can have different characters. For instance, the first entry in our table could be a thief, the second, a warrior, the third, a witch. And so our first question is, since Java is a strong typing programming language, which implies that everything on the left of the assignment operator = has to be of the same type as that on the right, "Is this requirement fulfilled here?" "Are we allowed to put thieves, warriors, witches, different, sub-classes of the class Personnage in an array of type Personnage?" The answer is in fact "yes". Actually, when we write an assigment where we assign to a variable of type superclass a reference to an object of type subclass, this is not in contradiction with the requirement that what is on the right of = has to be of the same type as that on the left thanks to inheritance of types in a class hierarchy that we studied on our last videos. So, an object of a subclass here, an object of type Sorcier, inherits the type of its superclass which is Personnage. Because inheritance is transitive, an object of a subclass inherits through transitivity all the types of its progenitors, and can have several types. These are aspects already considered in other videos, but are important enough to have to refresh. Our outline of the program is correct here: we are allowed to stock in an array of characters, characters of different types, which has the advantage of being able to manipulate in one combined way like here, with a loop 'for'. So let's see what happens when characters meet the principle character, particularly for certain subclasses of Personnage that have a peculier way of encountering someone. We examined before how a subclass can redefine a method in its superclass. And we took the example of a warrior who, when he encountered someone, would clobber him while other characters would perhaps merrily greet the other person. The problem we have now is if we store an object of type Guerrier, warrior, in a variable of type Personnage, what happens when we invoke the method rencontrer with this variable unPersonage? Will it be the method recontrer of the subclass that wil be invoked? Or the method of the superclass? This is exactly the same problem as in the introductory example, because we stock an object of type Guerrier in an entry of an array of type Personnage, that is a collection of type Personnage. It is important to know here if rencontrer will result in a simple greeting or a violent act. We can examine this question from 2 perspectives. We can first of all consider that the type of the variable on which is invoked the method will determine which method to use. Here, the type of the variable on which is invoked the method is Personnage. Then with this perpective, to decide the method we will look for the method in the class Personnage, and so the encounter will result in mere greetings. This way of solving this problem of finding which variable goes with which method is called in programming, the "...". We speak of static resolution because we don't need to wait for the program to be executed to make the choice of the method recontrer to apply here. If, by simply reading the code when the program compiles we can know unPersonnage is of type Personnage, consequently, it's the method rencontrer of Personnage that is applied. In summary, we speak of static resolution when it's the apparent type of the variable that determines which method to apply. Static resolution exists in certain languages, but not the perspective used in Java. The 2nd perspective is "dynamic resolution of links" where will will consider that it is the effective type, that is, the type that is stored inside the variable, that will determine which method to apply. In our example, the variable unPersonnage is evidently of type Personnage, but contains a reference to an object of type Guerrier. Because it is the type contained in the variable that is determinant, in this case we will choose the method rencontrer of the class Guerrier. So here, the character encountered will not only be greeted, but will also endure several blows. We speak of dynamic resolution because in general, it's during the program's execution that we will be able to determine what a variable contains in fact. So there are 2 ways of resolving methods in programming: statique resolution and dynamic resolution. Certain languages offer the choice between the two, that is we can choose if we want to use static resolution or dynamic resolution. In Java, this choice is not given, it's always dynamic resolution that is used. Thus it is the effective type which is stored in the variable rather than the apparent type of the variable that will determine the method to apply, and so, in our example, the warrior will fatally strike the character he meets. To close, let's summarize and synthesize with an example similar to the introductory one. Suppose that we have a class Jeu which contains a data member of type Personnage that would be the principle player, and another data member, an array of type Personnage, that would contain the opponents that will meet the player. The class Jeu contains a method public tourDeJeu that ensures that each adversary meets in turn the principle player. Suppose that in a constructor of the class Jeu, the array is filled like this: the first entry is a witch and the second a warrior. Suppose, like in other examples, that a witch simply meets another character by greeting them, and that the warrior encounters others by striking them. If a user of the class Jeu declares a variable leJeu, of type Jeu, and that it invokes the method tourDeJeu on this variable, what happens? If a static resolution is possible, the apparent type of variables is determinant, so Personnage is determinant. In this case, the player will be greeted twice: once by the warrior and once by the witch. But with a dynamic resolution, the method rencontrer will adapt itself to the type of the variable's contents, that is, the entry of the array. It is this effective type that is decisive, and so here, the player will be greeted by the witch, but attacked by the warrior. This second option, dynamic resolution, is what is always used in Java. So, this concludes this little introduction to polymorphism in Java. In the next episode, we will be able to come back to this notion in more detail.