We will consider in this lesson a very important aspect of programming: object-oriented programming (OOP). OOP is a programming paradigm or a certain style of programming that is used in several programming languages besides Java, which will give a certain number of useful features to your programs in terms of maintenance and modularity. At this stage of the course, you should know the fundamental aspects of basic programming. For example, you know how to write code to process data using control structures, such as conditional loops, You also know how to structure data using arrays, and, most importantly, you know how to modularize your programs using the paramount notion of functions. These basic tools allow you to code in a a certain style of programming, called procedural or imperative programming, in which data and data processing appear separately in the program. But the two entities interact: the data processing works with the data, which influence in turn the data processing. But the two entities appear separately. For example, the data processing can be represented with functions, and the data and functions can then be linked by the passing of arguments. The data is expressed by distinct entities, for example variables. One of the fundamental particularities of OOP is the possibility to bundle together functions and data into one same entity. Let's consider a concrete example. Imagine that we would like to write a program that works with the notion of rectangle. A rectangle is defined by its width, and its height. And I want to manipulate different rectangles to calculate their area. In procedural programming, I would proceed like this: I declare a variable "largeur" (TN: "largeur" means "width"), that I assign it a certain value. And, a variable for the height, that I would also initialize at a certain value. Next, I could calculate the area of the rectangle by passing its width and height to a function surface (TN : means "area"), that would do the right calculation. We see here that the data and the processing of the data are separated distinctly. The variables allow me to represent and store my data. And the surface function allows me to process the data. These two entities are separated in the program. But they are linked by the passing of arguments. The important objection that we could make for this program, is the lack of a semantic link between the two entities. For example, the semantic link between the width and height, which are in fact the width and height of a rectangle, is not very clear. If I don't speak the language, I don't understand what "largeur" and "hauteur" mean, it would be very hard for me to see that these two data are linked because they both refer to a rectangle. In the same way, the semantic link between the data and functions is hard to see. For example, imagine that I call my function, my method "produit" which is not very explicit, (TN: "produit" means "product") and that I am even less explicit in the names I choose for the arguments, so it is very difficult to see that I am calculating an area. So, save for this little explanation, the semantic link that exists between the data and the functions, is relatively obscure in this program. Yet this link does conceptually exist. It is indeed the notion of rectangle that I want to manipulate through its characteristics width and height. And it is indeed the surface of this rectangle that I want to calculate. So the fact of consolidating into one unit, a rectangle, the characteristics of the rectangle, that is its width and height , as well as the functions associated with it, will allow me to establish an explicit link between these different entities. This idea is fundamental to object-oriented programming. What you should know is that OOP enables a set of new functionalities, globally giving more robustness, modularity, and readability to your programs. All this allows for a better maintainability and robustness with regard to changes to the program. If it needs to be modified or expanded one day we would not want to have to rewrite the whole code, because of errors in the manipulation of data for example. Indeed, today most applications are never developed from zero, but consist of adding onto or maintaining existing code. And it is important to be able to do this at the lowest cost. We will see that the fundamental properties of OOP, that is, more robustness, modularity, and readability further this exact purpose. OOP offers, in fact, four principal concepts: encapsulation, abstraction, inheritance, and polymorphism that allow for better organisation of programs in regards to robustness, readability, modularity, and maintainability, as I said before. These central concepts are not exclusive to one programming language, but are central ideas of object- oriented languages in general. In this episode, we will consider defining encapsulation and abstraction. We will examine in the next episodes, the fundamental notions of inheritance and polymorphism. Encapsulation is consolidating into one unit or object the data and the functions that that work on the data. Typically, as in the example of the rectangle, we will regroup into one unique entitity, the width and height that characterize the virtual rectangle and the function that calculates its area. In jargon, we will speak of the data as member variables, or data members and the functions as methods. So in OOP, we will be able to define new data types, with the concept of classes. as we will see later. These data types can be used to work with data whose types are more abstract, like rectangles. These data will be objects that will cohabit and interact in the program. An object-oriented program will typically work with objects that are characterized by their members: data members and methods. Let's examine now the concept of abstraction. Let's say I want to write a program that manipulates several rectangles instead of just one. So in a procedural approach, I would have to declare as many widths and heights as I have rectangles. So like this for the first rectangle. And I would have to do exactly the same thing for the second rectangle. This is rather tedious! In the case that I have 3-dimensional rectangles that have not only a height and width, but also a a depth, so I would have 6 variables to initialize! For the area calculation for each rectangle, I would have to invoke the area method, and each time pass the correct arguments. We can imagine that this quickly becomes tireseome! This can also be a source of errors. Imagine that I mess up, and that I calculate the area with hauteur1 and largeur2. I loose coherence, and don't get the right values for the area of each rectangle. This mechanism, the encapsulation process, results in that I manipulate rectangles that are all clones if the same generic representation of a rectangle, with a width and height, and I have a area method that applies to all of them. As a result, I can work with higher-level data, the more abstract notion of a rectangle. Encapsulation will allow me to consolidate into this virtual rectangle everything needed to modelize it. As a result, I will be able to work with more abstract entities, a first rectangle, and a second rectangle, both of them are of type Rectangle. And I will invoke calculations of area on these rectangles. We will see that in object-oriented, I anticipate a little, I calculate the area of the first rectangle. Later on we will see all this explicitly in more detail. As a result, my program will focus on the important elements. Therefore I am no longer preoccupied with the fact that a rectangle has a width and a height, but I can concentrate on the essential aspects: The fact of working with a rectangle, and calculating the area of this rectangle. So when I use a rectangle, I can only see what we call in object-oriented jargon, its user interface, that is, what it can do, its functions that allow me to manipulate the rectangle, like in our case, the calculation of the area. Let us compare this with an everyday situation. When you drive your car, you normally only need to know the user interface. You need to know the steering wheel, the throttle, and the brake pedal, but you never need to know how the motor was built. So to drive your car, you only need to know the user interface. This applies to OOP as well. To use a new type of object, a new class, you only need to know the user interface, that is provided by the programmer of the class. The rest is internal implementation details that you do not need to know. So you can look at the object from two perspectives: from an external level, which is useful for the programmer-user, which uses the notion of rectangle in a program. From now in a program the type Rectangle exists. I can declare variables of type Rectangle, and initialize them appropriately. Next, that which interests me as a programmer-user, are the useful functions that come with the class: the calculation of area. So this external view is the perspective that interests the programmer-user and that uses the type Rectangle The second perspective is the internal. The programmer of the new type, the Rectangle type, had to deal with all the details of implementation. That is, that a rectangle has a length and width. He had to define explicitly how the area is calculated. This constitutes the implementation at an internal level, which not necessarily useful for the user of this type. So in object-oriented programming, we do not only have the possibility to regroup into one same entity the data and functions, but we can also define levels of visibility. The person who programs the type Rectangle, specifically the class Rectangle, will be able to say : " This is an implementation detail that will not be accessible to external users." and "This is a function that we want to provide for the external user and therefore will be accessible to this user." Everything accessible to the user and, therefore, visible constitutes what is called the user interface of the class of the type in question. Here, in our class Rectangle, for the new type Rectangle we have defined as user interface the calculation of the surface, the rest constituting the implementation details that are inaccessible to the user of the type Rectangle. Here we have the key that gives the program more robustness if they changes are made to them. Usually, when you change car even if the motor technology is different, the interface is more or less the same. You will still be able to drive, even if the internal details of implementation of your car have changed. So you only see your car as an abstract object. You only see that which you use to drive, namely, the steering wheel, the throttle, the break peddle. In summary, encapsulation, is consolidating into one same entity the data and functions that characterize it. And it is also the fact of concealing the implementation details, and defining a user interface of the class with the encapsulation mechanism, that will result in abstraction, and an abstract perspective of the object. We will only what the object has to offer in its user interface, and what manipulations are possible. So concretely the class programmer will decide on the existence of a new type, and will have to address the implementation details. He will have to decide what is visible to the outside world, what can and cannot be used. The class user, on his side, uses the new data type. But he will have to use it through the interface. That is to say, its visible methods in most cases. He will not have access to the internal details. The user interface is typically, that which will enable a link to be established between the program developer and the user. And in a very specific way this interface will be able to be completely described by the labels of the methods available to the user. So one of the principal advantages of abstracting and encapsulating is to give better visiblity and coherence of the program. Compare a procedural approach where I manipulate very low-level data, with the object-oriented approach which you will soon be able to code yourself. here I expressly manipulate a rectangle, as opposed to here, where this notion isn't clear. I establish the semantic link between the rectangle and the area, while here, this link is established very indirectly. So, the first advantage is more clarity, better coherence. Also, in this case, because the class user can only use the notion of rectangle through the user interface provided by the class programmer, it is possible for the class programmer to modify the class implementation without impacting the user. If the class programmer decides to change how he first implemented Rectangle, that represented the height and width with two doubles, and decides to use instead an array, then he simply needs to adapt the method to calculate the area to this new data structure, and the user will not be affected at all. Separating in two, the internal level: the implementation details, and the external user interface assures more rigorous usage framework. Any modification to the internal structure are invisible externally. A rule generally respected by most object-oriented programmers follows from this. Data members require technical choices to be made so that they can be used in the implementation, like choosing their type. They will therefore be considered in most cases as implementation details, and will not be accessible from outside the class. In summary, in order to define a new type of object with a class, we will have to define its characteristic attributes or data members as well as the methods that go with it. And we will have to determine concretely what will be visible in the user interface and what is not: the implemenation details. So once we have decided what to hide, the external user will only have an abstract view of this object through the user interface, and will only see that with a rectangle, you can calculate its area. And if I want to follow good OOP rules, I will consider that the data members are also implementation details, like I said before. Thus the interface will be limited to a certain number of well-chosen methods. The external user's vision of the object will be restricted to the user interface. What to remember from today's episode: abstraction results in what is called a class, which allows me to define a category of objects. A class will define a new type in a program. I now have the type Rectangle that I can manipulate in a program like this: I can declare variables of this type, which are actual realizations of this type. So the declaration of a variable of this type, is what is called in object-oriented jargon, an object. It is generally manipulated with a variable. To summarize and illustrate these remarks the person who writes the class Rectangle conceptually creates a new type. He will do this of course by writing a program that contains the code of the class Rectangle. The user of this class will use the new type, by declaring variables of type Rectangle that will only come into real existence at the execution of the program. So the moment the new objects of this type are created, we will be able to start working with these objects in the program. So the user will work with specific concretizations of objects of class Rectangle. We've come to the end of this presentation of two fundamental aspects of object-oriented programming : encapsulation and abstraction. You will, in the next episodes, start to put in practice these concepts in Java.