Intro to Object Oriented Programming - Crash Course

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everyone welcome to an introduction to object-oriented programming in this course we will be getting into what object-oriented programming means as well as going over its four main principles this course will assume that you have some knowledge of programming before hopping in if that's not the case i would suggest checking out our introduction to programming video which will be linked in the description that video will give you information on the basics of programming that are necessary to be able to understand more advanced topics such as those covered in this video for this lecture we will be exploring object-oriented programming in a manner that will be applicable for its use in any programming language in which it is supported examples will be used to explain the concept being discussed however they will be explained well enough that specific knowledge of the language being used in the example will not be necessary with that being said let's get into it in this first section we will be going over what object oriented programming actually is in order to understand what object-oriented programming is it's best to first understand what objects are and in order to do that it's best to first understand what primitive data types are so let's start there primitive data types are exactly what they sound like variables that store single simple values examples of such primitive types are the byte int float double boolean and char these primitive types only act to store a single piece of data of a certain kind and for a while when programming was still developing this was just fine many programs being written at the time weren't complex by today's standards thus programmers could get away with only using these primitive types however as programs became larger and more complex primitive data types weren't really cutting it anymore programmers began to want to group variables of similar type together why would this be useful well to serve as an example let's imagine you are trying to program a chess game when programming a knight into the game there are plenty of variables that you will need in order for the piece to work how it should for example you would need a position variable to keep track of where the knight is additionally you would need a boolean to represent whether the piece has been captured or not because if it has you would not want it to show up nor should you be able to move with it you may also need a variable to represent which color the knight is so that the game can treat it correctly these are just a few of the variables that you would need for one piece and you would need one of each of these variables for each piece on the board each of which would contain different data clearly it would be easiest if you could group all of the variables related to say one of your knights together so that you may deal with them as one entity additionally you may want to group your two knights together as they behave similarly you then may want to group the pieces of each side together as they would be treated differently in reference to each other in essence grouping related variables together is almost necessary when it comes to complex programs this is where the struct or structure came in in c the structure is similar to an array if you don't know what an array is i'd suggest you check out either our introduction to programming course for an overview or our data structure series for a more in-depth look at both arrays and many other data structures both arrays and structures allow the programmer to store several pieces of data together however structures vary from arrays in that structures allow the programmer to store data of different types together for instance whereas an array would allow you to store only ins or only strings using a structure you could store ins and strings together along with other data types a structure can even store other structures within it a structure can be very useful in the earlier chess example because you could store all of the useful pieces of data related to the knight in one structure that represents that knight you could then store your knight structures together in one structure that represents all of the knights and so on the structure allowed such grouping to take place beyond what arrays were capable of the structure is in many ways the precursor to the object which of course object-oriented programming is oriented around the main issue with using a structure in this way and an issue that objects would come to remedy was that you could not define functions within a structure you could only reference them when object-oriented programming came along objects allowed you to store data of all kinds together and additionally define and store functions now before we go much further i should get into exactly what objects are objects are instances of a class and a class is basically a template for an object this may seem like a circular way of looking at these concepts but allow me to explain let's say i define a night class in this class i would define and store data that is common of all knights this would be mainly the way that knights are able to move thus in this class i would define a function that uses the knight's current position to return squares that the knight can move to i may also define a position variable as well as a color variable but i would not initialize them when it comes to specific things such as variables that each object under the class in this case each night would have different data for it's best to define them when i create the object rather than in the class itself for instance each of the four knights that begin in a game of chess start on different squares than one another initializing the position variable in the night class would imply that you want each night object created from this class to begin with the same position which you do not however each of the knights would behave the same in terms of the squares it could move to based on their position and thus it is best to define a move function in the class rather than repeating the same function definition in each object that i create when creating a night object you initialize its attributes or its variables and its methods or its functions to contain information specific to that night whereas the night class represents any given night a night object represents one night in particular essentially object oriented programming is the best tool us programmers have right now to create complex programs by grouping together related data and functions throughout the course of this video we are going to be getting into detail into how all of this works using the four main principles of object object-oriented programming those being encapsulation abstraction inheritance and polymorphism this next section is going to be focusing on the first of the four main principles of object-oriented programming encapsulation encapsulation refers to bundling data along with methods that can operate on that data within a class essentially it is the idea of hiding data within a class that anything outside that class cannot directly interact with that is not to say that they are unable to interact with the separate object's attributes at all however instead members of other classes looking to interact with the attributes of an object should only be able to do so through that class's methods in practice one way this tends to work is by creating getting and setting methods these methods act to either get information from an object or set attributes to different values for instance think back to the chess example from the previous section if i was moving one piece and i wanted to determine whether it was able to capture another piece i would need to define a dot get method associated with each piece that returns the piece's color in this case piece dot get color this way i could check the color of any piece from anywhere in my code without having to access the internal attributes of said pieces this allows us to retrieve the information from where it is defined additionally this makes it easiest to keep track of attributes that depend on one another for example if i was programming a game i may have two different attributes for the player's health max health and current health when the character levels up i may have their max health increase as well when this happens i would want the current health to be set to the maximum health instead of changing both of these values directly i can define the set max health method such that the current health is also set to the maximum health once the maximum health has increased furthermore these setting methods allow values to be validated for instance if current health is not able to exceed maximum health then i would have the set current health method check if current health would be greater to maximum health before making the change finally you may want some values to be read only from outside a class which means you would only define a getter method and not a center method for another example let's look back at chess when dealing with a piece's position you would want to keep track of its rank or its row and its file or its column when the piece moves you may think it would be okay to just set piece.rank and piece.file to new values however as discussed above this is not the best way to handle it it would be better to define a pst.move function that takes the intended new position and checks if that is indeed a valid move the piece would not be able to move if say the new location is off the board a piece of the same color is already on that square or making such a move would put the king of the same color in check additionally other methods may be called from this move method for instance one that captures an enemy piece if it was on that square or one that puts the enemy king in check were the pieces attributes just to be directly changed you could end up in a strange situation where illegal moves are played and pieces occupy the same square essentially getter methods allowing validation can be very useful encapsulation is useful for a variety of reasons as we just went over it is best to not allow anything external to directly edit an object's attributes this is especially true when working on large and complex programs where you may want individual pieces of the program to work well without requiring them to rely on every other section of the code in this way preventing each piece of your code from referencing and requiring knowledge of the inner workings of each other section of code is very important to keep your program from becoming completely entangled in itself this is an idea we will touch upon in future sections to come but for now it's best to understand that information hiding that is keeping one class from being able to directly access the data of another class is important to keep control of your program and reducing its overall complexity overall encapsulation is a vital component of object oriented programming that allows the programmer to maintain control of their data and to keep their program from ending up in any unwanted states in this next section we are going to be discussing the next of the four main principles of object-oriented programming abstraction abstraction refers to the idea of only showing essential details and hiding everything else this idea is present in everyday life when you drive your car there are some things you need to understand about you need to understand how the steering wheel steers the car and how the gas and brake pedals work you also need to know how much gas your car has and that it needs gas to work these are necessary details for you to be able to drive the car properly however the exact way that the car works internally isn't something that most people need to concern themselves with how the gas reacts in the engine and how that translates into the car moving forward really isn't important while you are driving your car all that matters is that you know it will work this way whoever built the car had to worry about how exactly the car would work so that you don't have to this idea extends to object oriented programming the classes you create should act like your car users of your classes should not worry about the exact inner details of said classes this idea is similar to that of encapsulation that we discussed in the previous section earlier we mentioned how you should not have classes directly interact with the data stored within other classes rather have them use the class's methods to access their data this idea is especially important when you want to work on your program incrementally where you focus on one class at a time and ensure that it works this is a very useful approach as it can be difficult for you to focus in the big picture while programming and splitting up your project into smaller chunks can make it much more manageable furthermore programs nowadays are vast and complex to the point where multiple programmers tend to work on one project in this case it's best if the section that you are working on is able to function without knowledge of the inner workings of your colleagues section to achieve this it's best to think of your program in terms of interface and implementation the interface refers to the ways that sections of code are able to communicate with one another this is typically done through methods that each class is able to access the exact implementation of these methods or how the methods are coded should be hidden within the class and not accessible from the outside think of this like the car the other classes are able to turn the wheel and push the gas and they know what the outcome should be without caring about exactly how this gets done let's return to the chess example that we've been using throughout the video let's say that you are working on making the night work as it should and a fellow programmer is working in the king class in order to effectively work together you need to agree on an interface with which these pieces are able to communicate in this case say that you are working on making the knight unable to move if your king is in check as the programmer of the night class you make the knight use the king's getter method that will let the knight know whether or not the king is in check if it is then you make it so the knight is not able to move unless it is able to put the king out of check as you program the night class you should not be concerned with how the king is determining whether or not it is in check the king's method that tells the knight whether or not it is in check as part of the interface but how exactly it does that is part of the implementation this manner of only allowing the classes to interact through a predetermined interface prevents different pieces of the program from becoming completely coupled together if the night class has to look into the king class in order to make a determination then it is reliant on the king class being set up in a certain way in order to function if the king class is changed or reorganized or its data is renamed then the night class would no longer work and it too would have to be changed assuming the rest of the program was coded in this way then many other classes would also have to be modified creating a set interface through which classes can interact with one another ensures that each individual piece can be changed without creating a ripple effect that causes the entire program to have the change in response overall it's best to keep in mind abstraction when writing object-oriented code as it allows the program to be worked on incrementally and prevents it from becoming completely entangled in itself and very complex determine specific points of contact that can act as the interface between classes and only worry about the implementation behind it when working on that section this next section will be tackling inheritance the third of the main principles of object-oriented programming inheritance is the principle that allows you to derive classes from other classes classes can inherit certain methods and attributes from another class we will get into exactly what this means in a moment but first let's look at an example let's say you are programming a game in this game the player has access to weapons to fight their enemies to begin you may establish a weapons class this class would contain many of the pertinent attributes and methods common to weapons for instance an attribute that represents the damage that the weapon deals and a method that deals damage to an opponent when called you then would want some more clashes to represent specific weapons such as a sword or a club these classes would act differently from one another as swords and clubs have certain different attributes such as a sword being made for cutting whereas a club is blunt these differences would be represented in different values for their attributes as well as possibly different attributes altogether however they do share much of the same behavior as they are both members of the weapons class in this case the weapon class would be the superclass and the sword and club classes that extend the weapon class would be subclasses in relation to it many of the attributes and methods associated with the weapon class would also be present in its subclasses any given sword or club would also want access to the methods that allow them to deal damage as well as the attributes that detail how much and what type of damage they deal the class hierarchy does not tend to be so small however as in most cases there are many more layers than just one superclass and a couple of subclasses the weapon class may be a subclass to a broader items class which could contain many other subclasses with subclasses of their own additionally you may include a wider variety of weapons than just swords and clubs as well as multiple types of swords that would require different behaviors and thus their own subclasses when you are writing object-oriented code many of the classes you create will fit somewhere in the broader class hierarchy which acts as a web of classes with different relationships to one another the next important topic to cover in terms of inheritance is the access modifiers that change which classes access which attributes methods or even classes as a whole there are three main access modifiers that we will be discussing public private and protected let's begin with the public modifier public is probably the most simple of the modifiers a public member or class can be accessed from anywhere this includes any super classes subclasses or anywhere else in the program this is very useful when you need to have access from a wide variety of places in your program to better understand this modifier and those to come look to the example class hierarchy on screen that represents different foods for each example the member in question will be defined in the fruit class green classes have access and red classes do not as you can see a public member being defined in this class or anywhere else can be accessed from anywhere in your program next we have the private modifier private members can only be accessed from within the same class that the member is defined this is best to use if you do not need this information accessed from anywhere else in the program additionally this allows you to create other private members of the same name in separate classes which will not conflict with one another due to their private access modifier as you can see on the example class hierarchy a private member defined in the fruit class can only be accessed inside the fruit class we then have the protected modifier a protected variable can be accessed from within the class it is defined as well as any subclasses of that class essentially protected variables are private to the class hierarchy that they are defined in this can be seen in the example class hierarchy right now in this final section we will be covering the final of the four main principles polymorphism polymorphism describes methods that are able to take on many forms there are two types of polymorphism the first one is what is called dynamic polymorphism dynamic polymorphism occurs during run time when the program is being executed this describes when a method signature is present in both a subclass and a superclass the methods share the same parameters but have separate implementation in this case the subclasses implementation of the method overrides the superclasses let's go over an example let's say you are writing a program to represent many different types of cars in a class hierarchy at the top of the hierarchy you may have the generic car class you then may create a sports car class as a subclass of the car class you then may create a dot drive method in both of the classes in each of the classes the dot drive function will take a double representing the number of miles you would like the car to drive and the car's gas attribute will be decreased by the pertinent amount in the car class the dot drive function may cause the car's gas to decrease by 0.04 gallons per mile whereas the sports car class may instead have its gas decreased by 0.02 gallons per mile it drives if you create an instance of a sports car called my sports car the sports car implementation of the dot drive method will override the generic car version of the dot drive method therefore mysportscar.drive will decrease my sports car's gas attribute by 0.02 gallons per mile however were you to create an instance of the car class called my car my car.drive would instead decrease my car's gas by 0.04 gallons per mile this is an example of dynamic polymorphism as the implementation of a method signature can change depending on which level in the class hierarchy that it is called this works this way because the form of the method that is called is decided dynamically as the program is run this idea can be extended across the class hierarchy in more layers than just two you could add more subclasses representing different types of sports cars with their own.drive methods with different implementations and creating an instance of each of these subclasses would use their own implementation of the dot drive method when call the main benefit of dynamic polymorphism is that it allows you to write methods in the superclass without having to include ifs and else shifts to account for exactly which subclass is being used when the method is called the second type of polymorphism is static polymorphism static polymorphism occurs during compile time rather than runtime this refers to when multiple methods with the same name are defined in the same class in this case the methods are differentiated by their arguments either they take a different number of parameters they take parameters of different types or they take parameters in a different order than one another this is known as method overloading despite the names of the methods being the same they have different method signatures due to their differences in the parameters that they accept to better understand this let's go back to the car example let's say that you are working within the car class in this class you are looking to create three different drive methods the first drive methods argument accepts one integer and one string as parameters say speed and destination for clarity we will refer to this one as drive method one however keep in mind that its method name is just drive for drive method 2 we will set its argument to accept two integers for instance distance and speed finally in drive method 3 we will have it accept a string first for destination and then an integer for speed this differs from drive method 1 in that drive method 1's parameters are in reverse order compared to drive method threes in each of these three example methods the method signature is different despite the methods having the same name therefore the computer is able to tell the methods apart when the program is being compiled for example were i to call mycar.drive45 work drive method 1 would be called as the argument given indicates that this is the method i would like to call furthermore my car.drive 1560 would call drive method 2 and mycall.drive school 30 would call drive method 3. when implementing method overloading the different methods tend to have separate but similar effects despite drive method 1 and drive method 3 taking the same parameters it is likely that their implementation would be different and thus would achieve separate effects otherwise there would be no reason to have both methods keep in mind that method overloading can cause trouble if you do not keep straight which of the methods implementations you would like to execute and what form of the argument is required to do so normally if you call a method with too many parameters or parameters of the incorrect type then the program will throw an error and you will be able to fix the issue however if you mistake the methods argument in such a way that one of the other methods with the same name is called instead then you may not even be aware that you made a mistake overall polymorphism simply allows methods to take on many different forms it can be very useful in that it allows methods of the same name to exist both in the same class and in different classes however you must be careful to ensure that you are calling the correct form of the method that you want so your program can function as intended that does it for polymorphism and with the end of polymorphism the final of the four main principles comes the end of this video on an introduction to object oriented programming if you enjoyed consider liking and subscribing to null pointer exception and check out some of our other videos in which we cover a variety of other topics that you may find helpful thanks for watching
Info
Channel: freeCodeCamp.org
Views: 337,524
Rating: 4.956326 out of 5
Keywords:
Id: SiBw7os-_zI
Channel Id: undefined
Length: 30min 17sec (1817 seconds)
Published: Wed Sep 30 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.