Defining Inheritance Concept 0:00Inheritance allows one object to acquire, or inherit, the traits and behaviors of another object. And this should instantly make sense, in the same way that a child inherits their qualities from a parent. Same basic concept. So I'll show you a few fun examples. Let's say you have a coffee maker, and a coffee maker has the ability to brew coffee. So here, if I were to dump brewing the coffee, we can now instantiate our coffee maker and call brew. So now, if I run this file, of course it works. Coffee Maker Inheritance Example 0:32call brew. So now, if I run this file, of course it works. Okay, but I also saw a commercial for these specialty coffee makers that can also brew a latte. So here's the problem, though. If I were to say brew latte, well, that doesn't make any sense, because a standard coffee maker can't do that. So now we have this specialty coffee maker. And here, we could add brew latte. But now here's the thing.And here, we could add brew latte. But now here's the thing. A specialty coffee maker can still brew a basic cup of coffee, and I don't want to have to repeat myself here. So instead, why don't we leverage inheritance, and we do that with the extends keyword. Now, a quick note here. Notice that we have a is-a relationship. A specialty coffee maker is a coffee maker. And this will just about always be the case, at least you want it to. And if it's not, if there's no relation there, you probably want something called compositionAnd this will just about always be the case, at least you want it to. And if it's not, if there's no relation there, you probably want something called composition instead, and we'll review that together soon. So now, if I were to swap this out and run it again, yes, a specialty coffee maker can still brew basic coffee. However, it can also brew a latte, and that is inheritance. In this case, the child inherited the behavior of the parent. But then, it can extend that functionality however is appropriate. Let's review another example. Let's say this time we have a collection. Building a Collection Example 2:01Let's review another example. Let's say this time we have a collection. And of course, a collection consists of items, an array of items. Let's go ahead and build that constructor up. Now, let's say we're going to have a collection of videos. So we'll have a class called video, and we'll just do some public properties here, like the title of the video and its length. And once again, I'll build that up. Okay. So let's say down here, we're going to instantiate a collection, and we're going to pass anyOkay. So let's say down here, we're going to instantiate a collection, and we're going to pass any number of videos. They might be from a database, or you might be doing it on the fly. It doesn't matter. This video will be 100 seconds long. This one will be 200, 300, like so. Okay. So now, if I were to save that, and then we var dump the collection, if I now run this, sure enough, we have a collection of three items.So now, if I were to save that, and then we var dump the collection, if I now run this, sure enough, we have a collection of three items. Okay. So let's say right up here, of course, a collection class would have any number of methods, but we're just going to add one for the example. And we can either do this by accepting a callable, or let's just accept a key here. You give us the key, and we will calculate the sum, or the total, for every item within this array that has that key. So if the key was this property length, then we would get the total of 100, 200, and 300. Okay.So if the key was this property length, then we would get the total of 100, 200, and 300. Okay. Here's how we might do that. First we need to map over the array. So let's look into our items there. And for each one, we need to use the key. And all I'm going to do here is just return item key. We'll assume it's publicly accessible, at least for now. All right. So is this clear?All right. So is this clear? At the moment, this item's array is equal to these three items. So we're going to map over it. We'll loop over it, and we're going to build up a new array. And that new array will contain only the key that we provide. So if I were to say collection sum, and we provide length, it will look for this property. Okay. So now at this point, we would have a new array of whatever those values were, something like that.So now at this point, we would have a new array of whatever those values were, something like that. At this point, we only need the sum, and I can use array sum for that. So that'll give us the sum of all these values, and we will return that. All right. So let's give it a shot. We have our collection, and we want the sum of all those length items. So if I run it again, now we get 600. 100 plus 200 plus 300 is 600. It works. Creating a VideosCollection 4:36100 plus 200 plus 300 is 600. It works. Now, this isn't overly clear to me, though. We're using this sum method because it works, but what we are really checking is the length of all the videos. And in fact, why don't we make this more clear? I have a collection, but it's really a collection of videos. So now I want to say, oh, not sum, but how about the length of all the videos? So now we have a new issue. In this context, length is very specific to a collection of videos.So now we have a new issue. In this context, length is very specific to a collection of videos. So it really wouldn't make too much sense to add a method here called length because, again, it's unique to videos. So this is an example for inheritance. Let's create a new class called VideosCollection, and we'll have it extend our collection. And let's do that check again. Do we have an is a relationship? Is a VideosCollection still a collection? Yes, it is.Is a VideosCollection still a collection? Yes, it is. So we're good to go. Now we have a new place to store domain-specific logic for videos alone. And here's what's neat. Because we've inherited all of this behavior, all I have to do is defer. Let's call the sum method on the parent and then pass through the key. So notice it's the same thing, but we are wrapping it in a more domain-specific terminology. So now we have a collection, but specifically, a VideosCollection. And I want to grab the length of all the videos.So now we have a collection, but specifically, a VideosCollection. And I want to grab the length of all the videos. Let's run it, and we get 600, which is correct. So that completes our second example. And actually, real quick, before we move on, I think we can refactor this. So a couple things. First, I'm using PHP 7.4 here, which means I could use short array functions. So I can convert this. And I'm a big fan of this approach. Because notice, it cleans up the code, and it also removes the necessity to add thatAnd I'm a big fan of this approach. Because notice, it cleans up the code, and it also removes the necessity to add that horrible use keyword every time you reach for a closure. So that's nice. But actually, in this case, I'm not even sure we need a function. Because as it turns out, once we were finished, we realized we're just using ArrayMap to grab all of the keys from each item. So in situations like this, a more elegant approach would be to use ArrayColumn. So here, you would give it the items you're looking through. And as a second argument, you want the column name. Real-World Inheritance Use Cases 6:55So here, you would give it the items you're looking through. And as a second argument, you want the column name. So that should do the exact same thing. And real quick, if we try that out, we still get the correct answer. So yeah, that's a much cleaner approach. Anyways, let's move on to a third example. So if you work with Laravel, of course, you'll have things like this. Maybe you have a class post that will extend a model. So not only does post now inherit all of the functionality from a model, but again, a post model is still a model.So not only does post now inherit all of the functionality from a model, but again, a post model is still a model. It's just a specific type of model. Here's another one from my own codebase. I have this class achievement type that we use for the various achievements on Laracast. However, I also inherit from this class, or you might hear it referred to as subclassing. And this allows me to create a class for each achievement type. For instance, after you get your first thousand points, you get an achievement. So we can use inheritance for this. So again, that is a relationship is true.So we can use inheritance for this. So again, that is a relationship is true. Now you should be thoughtful about inheritance. You don't want to reach for it all the time. However, there are situations when it makes for a better API and a better presentation, especially when others are using your code. So for example, if every achievement type has a name, maybe it has a category or a difficulty. Maybe every achievement type has an icon and every achievement type has a qualifier. So this would be where you accept a user. And this method determines if the provided user qualifies for the current achievementSo this would be where you accept a user. And this method determines if the provided user qualifies for the current achievement type. Okay. But here's the thing. You may realize, oh, if we look at the class name, we can figure out likely what the name of the achievement is. And we can also figure out what the icon type is. If you're following a convention, maybe the icon is first thousand points dot PNG in your images folder.If you're following a convention, maybe the icon is first thousand points dot PNG in your images folder. You know, we can automate this. So it would be nice if we could default to those values, but still allow the child to override them if necessary. And the same might be true for difficulty. If your default difficulty is medium, we don't want to repeat ourselves over and over if that's going to be true in many of the cases. Okay. So here's what we do.Okay. So here's what we do. We take those methods and we move them to the parent. Now I'm not going to worry about writing this out, but yeah, you might read the class name. You might hunt down every capital letter and replace it with a space. So that way you would end up with a name of achievement type. This might hard code it. It defaults to intermediate. The icon might return a look in the images folder and then again, maybe convert this to lowercase and you're going to look for that dot PNG or something like that.The icon might return a look in the images folder and then again, maybe convert this to lowercase and you're going to look for that dot PNG or something like that. So now you have these defaults that are out of sight, which makes the child that much cleaner. Whenever I have a new achievement type, I don't have to worry about all this stuff. The main thing I care about is the qualifier because that will be unique for every single achievement type. But everything else, yeah, we can tuck that away in a parent class. I don't want to look at that every single time I create a new achievement. However, there will be cases though, where you do have a special name that doesn't match Overriding Parent Behavior 10:05I don't want to look at that every single time I create a new achievement. However, there will be cases though, where you do have a special name that doesn't match the class name. And in those cases, you override the parent. So now we have a new concept. Yes, inheritance allows us to inherit the behavior of a parent, but we also have the ability to override that behavior entirely. So in this case, if achievement type has a name method and the child class has a name method as well, we will defer to this one. All right, that'll get us started with inheritance.method as well, we will defer to this one. All right, that'll get us started with inheritance. In the next episode, let's talk about abstract classes.