در حال بارگذاری ...

Introducing Inheritance0:00

Welcome back. Thanks for sticking around. Next up, we move on to inheritance. And yet again, it sounds a little tricky. It sounds a little scary. It's really just not. Alright, so think about it. As a human, you inherit certain traits from your parents, right? Maybe your eye color, or your hair color, or your strength, or height, or things like that. Alright, so you, as Jane, or Joe, the children, inherit characteristics from your parents. Alright, so we have a parent-child relationship. Or another way to think of it is, you, as Joe or Jane, are almost like a specialized version of your parent. You inherit some things, but you are your own entity, right? So, the same thing is true in the programming world. And I'll give you a couple different examples, but first up, I want to start with something super, super lame and generic in real life, but it'll help get the point across. Alright, so imagine you have a class called Truck. Alright, what does a Truck do?

up, I want to start with something super, super lame and generic in real life, but it'll help get the point across. Alright, so imagine you have a class called Truck. Alright, what does a truck do? Well, a truck goes, right? It moves. It can accelerate. It can stop. And then also, it has certain, like, traits or qualities, like a color, a maker, a model, a number of wheels, right? But at its core, what is a truck? Well, a truck is a car. Or you could say a truck is a vehicle. And notice those two words in the middle, is a. That is a key component to inheritance. At any point, you should be able to say the child class is a type of the parent class. So, remember with the human example, Joe is kind of a type of his parent, and Jane is a type of her parent. In this case, Truck is a kind of Vehicle. Now, we could also say a Van is a kind of Vehicle. Maybe even something like a Cart is a kind of Vehicle. So, Cart inherits from Vehicle. Because if you think about it, all these

Vehicle and Cart Example1:56

of vehicle. Now, we could also say a van is a kind of vehicle. Maybe even something like a cart is a kind of vehicle. So, cart inherits from vehicle. Because if you think about it, all these different things, a car, a truck, a cart, a moped, anything like that, they share certain behavior. And that behavior is they can move, and they can stop, and maybe they have a name, and maybe they have a color. Alright, so with that in mind, why don't we create two classes here? The first one will be the parent, and in this case, the class is vehicle. The second one will be the child, and the child is a kind of parent. It's almost like a specialty version of the parent. Now, some things will differ, but some things will remain the same, right? So, I can define inheritance by saying class cart extends or inherits from vehicle. So now, it's going to literally inherit any of the behavior that was defined on vehicle. So, for example, if we had a method called accelerate, and I'm just going to

Cart extends or inherits from Vehicle. So now, it's going to literally inherit any of the behavior that was defined on Vehicle. So, for example, if we had a method called accelerate, and I'm just going to echo accelerating. Now, even if I instantiate not Vehicle but Cart, I will have access to an accelerate method. Have a look. new Cart(), and notice we have access to accelerate. Let's give it a run. php on the current file, and we get accelerating. So, now you see what I mean. This class is literally inheriting from its parent. That's the entire point. But now, just as Joe will inherit qualities from his dad, but that doesn't mean he is his dad. He is his own person, and he will have his own behavior and his own characteristics. So, for example, maybe, yeah, for Cart, maybe to demonstrate the example, when it accelerates, well, it doesn't hit the gas or it doesn't work with a motor. It just rolls or something like that. So, we're going to represent that by saying rolling. You get the

Notification Subclasses3:54

the example, when it accelerates, well, it doesn't hit the gas or it doesn't work with a motor. It just rolls or something like that. So, we're going to represent that by saying rolling. You get the idea, right? It's just a different way for a Cart to accelerate versus what a Truck would do versus what an ElectricCar would do. All right. So, now, take a look at this. Cart is inheriting behavior from Vehicle, but also, at any point, it can override that behavior. So, if I run this again, now it's going to say rolling because we've overwritten the accelerate method, and that's totally fine. Cool. But, yeah, if it doesn't need to override it, it can defer to the parent, as you see here. Very cool. All right. Now, let's move on to something a little more practical to the web development world. How about something like an achievement, or how about a Notification? Yeah, this is a good example. Let's go with Notification. So, a Notification is basically a message that we

development world. How about something like an achievement, or how about a notification? Yeah, this is a good example. Let's go with notification. So, a notification is basically a message that we send to the User, right? All right. So, what were the verbs? Well, I said send, right? So, that's my verb. Why don't we represent that in the code? And I'm going to echo this to represent a default notification. Maybe, I don't know, a flash message. Show pop-up flash message. Cool. So, now, I could create a notification and call that send method. Notification, and now I can say notification sent. And sure enough, if we clear this out and give it another run, we defer to that functionality, and that's great. But now, are there different ways that we could notify a User? And the answer is absolutely. For example, rather than showing a flash message in the bottom right corner of the screen, which we've all seen, maybe instead that notification should be emailed to them.

is absolutely. For example, rather than showing a flash message in the bottom right corner of the screen, which we've all seen, maybe instead that notification should be emailed to them. Something like, hey, we wanted to notify you that we couldn't process your subscription renewal, or something like that. Well, now, we have a problem, though, because the send method on notification assumes a flash message. And maybe, yeah, in real life, it's putting something into the session or something like that. All right. So, now, it's like we need a specialized version of a notification. Well, what should we call it? Well, here's what I like to do. Speak out loud. We've gone over this. What is it? Well, it's a notification that emails. So, it's like an email notification. There it is, right? Your class is EmailNotification. All right. So, now, I still want to inherit a certain behavior from notification. For example, when you instantiate notification,

notification. There it is, right? Your class is EmailNotification. All right. So, now, I still want to inherit a certain behavior from Notification. For example, when you instantiate Notification, you probably need to include the body, the copy, the message that we send to the user. So, let's accept that as message. And then, I'm just going to make it public here for now. All right. So, now, I still want EmailNotification to have access to message. So, it's going to inherit from Notification. extends Notification. All right. So, let's do that is a test. Is an EmailNotification a kind of Notification? Yes. Makes perfect sense. This is a good example. Okay. So, now, if I replace this with new EmailNotification, yes, of course, I can still defer to the send method. And, yes, I can echo the notification message. Here is my notification. All right. Let's give it a run. And, sure enough, we see our message. That's working great.

to the send method. And, yes, I can echo the notification message. Here is my notification. All right. Let's give it a run. And, sure enough, we see our message. That's working great. But, yeah, now, when I call notification send, it's still deferring to that default implementation, which is to show a flash message. And that doesn't make sense in this case. So, now, EmailNotification is a special version of Notification. And what makes it special is it actually fires off an email. So, let's say send. Overwrite that behavior. And, yeah, once again, you would defer to your mail service in whatever form that takes. In this case, once again, to demonstrate it, we'll just say fire off an EmailNotification. All right. Let's give it a shot. We run it again. And, now, an EmailNotification sends by, well, firing off an email. Makes perfect sense. Cool. Now, you can even imagine other specialty versions.

All right. Let's give it a shot. We run it again. And, now, an email notification sends by, well, firing off an email. Makes perfect sense. Cool. Now, you can even imagine other specialty versions of notification, like, I don't know, oh, a browser notification, right? So, you know, some websites will request to send you OS level notifications. I don't know what you call those browser notifications, OS. Why don't we call it OS notification? All right. Let's have a new one, OS notification. And we'll say dispatch an OS specific notification. And I think we have JavaScript APIs that can do that now. Yeah. So, now, we have a base Notification class that has a set of characteristics and behavior. But then we have child versions that are like specialty implementations, specialty versions of a Notification. One sends an email. One dispatches an OS specific notification. But in every single example, just to reiterate this, the subclass,

Achievement System Design9:08

specialty implementations, specialty versions of a notification. One sends an email. One dispatches an OS specific notification. But in every single example, just to reiterate this, the subclass, and that's how we can think of this, the child, the subclass, we can use those interchangeably, are types of the parent. All right? Very, very cool stuff. Now, should we use one more example? Yeah, I think we should. I want to show you abstract classes. So, let's clear all of this out. And let's return to this idea of an achievement. So, many websites will offer an achievement system, right? We have one at Larikas. You get achievements for doing various things around the site. For example, if you publish your first forum conversation, you get an achievement badge. If you help people out, you receive a best reply award. You get an achievement badge, right? If you watch your first video, if you watch 100 videos, you get a different

an achievement badge. If you help people out, you receive a best reply award. You get an achievement badge, right? If you watch your first video, if you watch 100 videos, you get a different achievement badge. So, think about it. When you implement this functionality, well, an achievement would require like a name, right? Some kind of cute name. Something like a blasting off, and that would be you watched your first video or something. Maybe an achievement has a description that describes what it represents. Maybe an achievement is associated with some kind of icon that you display. And then finally, maybe the achievement has behavior that determines whether or not the given user qualifies for that achievement. So, for example, I said you get an achievement badge if you watch 100 videos. All right, well, we need some logic that inspects a user, right? It looks at the user, it fetches how many videos they've watched, and it checks,

achievement badge if you watch 100 videos. All right, well, we need some logic that inspects a User, right? It looks at the User, it fetches how many videos they've watched, and it checks, is that greater or equal to 100? So, we might call that like a qualifier. It checks whether the achievement or the User qualifies for the achievement. All right. So, let's add that method, qualifier, and it's going to accept a User. Now, in this case, I'm just going to quickly create a dummy User for our example. Great. Now, what else? I said an achievement has a name, a description, and an icon. Why don't we accept those in the constructor? string, or let's make it all public. Public string name, public string description, and then finally, public string icon. Now, a quick little note, when you have super long lines like I have here, there's nothing wrong with putting each of these on their own line, like so. That's kind

and then finally, public string icon. Now, a quick little note, when you have super long lines like I have here, there's nothing wrong with putting each of these on their own line, like so. That's kind of a good practice to get into. You could even do this. People kind of differ on what they like to do there. Nonetheless, this is fine. All right. So, it's starting to make sense. An Achievement consists of a name, a description, an icon, and then it also has behavior called qualifier. Great. So, why don't we try one out? Let's do that one for firstPost. firstPost equals a new Achievement badge. Now, I'll give it a name of firstPost, description, granted when you create your firstPost, whatever. A little redundant. And then finally, the icon might be firstPost.svg. Cool. So, this all is good, and if I die and var_dump the firstPost, or just var_dump, if we give it a run, yep, we get an object that has the name, description, icon. That all makes sense.

So, this all is good, and if I die and var_dump the firstPost, or just var_dump, if we give it a run, yep, we get an object that has the name, description, icon. That all makes sense. But how do we handle the qualifier here? Because think about it. For each achievement, the qualifier is going to be different. All right. Well, there's a couple ways we could do this. We could pass through a qualifier as an anonymous function, as a closure that we send in when we register the achievement, or each achievement could be its own subclass of this parent. So, let's give that a shot now. Let's create another class, and this will be FirstPostAchievement. All right. It's going to inherit, so we'll say extends Achievement, and now we don't have to double up by accepting the exact same constructor arguments. So, now we are allowing for more consistency and reusability, which is one of the benefits of inheritance. But now, yeah, the

double up by accepting the exact same constructor arguments. So, now we are allowing for more consistency and reusability, which is one of the benefits of inheritance. But now, yeah, the qualifier, I'm going to override that, like so. And yeah, excuse me. This is going to, once again, inspect the user's, I don't know, participation on the site. So, we don't have this logic, but it might be like if it's related to the user's posts, then grab all of their posts and check if the count is greater than zero. Something like that, right? Some kind of conditional that returns true or false to indicate if the given user qualifies for this particular badge. All right. So, I'm just going to hard code it and say true here. All right. So, now I'm going to instantiate our firstPostAchievement, and now let's call firstPostQualifier, and why don't we say if that's truthy, then they qualify. Otherwise, they do not qualify. And yeah, maybe you can

our firstPostAchievement, and now let's call firstPostQualifier, and why don't we say if that's truthy, then they qualify. Otherwise, they do not qualify. And yeah, maybe you can run this logic and then update records in a database or something like that. All right. We give it a run, and we get nothing. We forgot to echo. One more time, and they qualify. All right. So, now we have a subclass that inherits from a parent class. Very cool. But now we have this odd situation where I did want to inherit from the parent, but the parent includes behavior that doesn't really have a default implementation. Like maybe the default implementation is, sure, you qualify for everything. Everyone gets an award, as my parents like to complain about. Yeah, that doesn't really make sense. But at the same time, I want to indicate to every child class that, hey, this is something you need to offer. You need to include a qualifier method. Or in

Abstract Classes Enforcement15:15

Yeah, that doesn't really make sense. But at the same time, I want to indicate to every child class that, hey, this is something you need to offer. You need to include a qualifier method. Or in other words, every single achievement requires logic that determines whether or not the user qualifies. So, what do we do here? Do we get rid of it entirely because there's no default implementation? Well, no, that doesn't make sense because now there's no enforcement. This class could have a qualifier, but it could just as easily not have a qualifier. And we're not going to get any kind of enforcement. There's no checks and balances there. So, here's what we do. It sounds like achievement itself you would never instantiate on its own. You would always instantiate one of the subclasses, right? So, with that in mind, I'm going to make this abstract. I have this keyword here. And yeah, this always confused me in the early days. Just think of it.

instantiate one of the subclasses, right? So, with that in mind, I'm going to make this abstract. I have this keyword here. And yeah, this always confused me in the early days. Just think of it like this. When a class is declared as abstract, it means you should never instantiate this on its own. And it's not even going to allow you to do that. All right. So, watch this. If I were to try to instantiate Achievement, notice my editor doesn't give me any auto-complete because it's not allowed. So, if I try to run this, it's going to fail with an error. Hey, you're trying to instantiate an abstract class, and that's not allowed. You declared it as abstract, which means you can't do the thing that you're trying to do right now. Okay. So, what is the benefit to an abstract class? Well, here's what it is. It's an indication that, no, you should inherit from me, but you should never instantiate me. And then further, we can define behavior.

benefit to an abstract class? Well, here's what it is. It's an indication that, no, you should inherit from me, but you should never instantiate me. And then further, we can define behavior on the parent class that must be implemented by the child. For example, if I declare abstract public function qualifier, watch what happens here. Now, if firstPostAchievement omits that method, I'm going to get a red squiggly line here. Let's see what happens. If I hover over it, hey, class must be declared abstract, or it must implement the method qualifier. So, once again, right here, we're saying, all right, this is almost like an interface. It's kind of another way of doing it. We're saying, all right, any subclass who inherits from me must implement this behavior, and I create that enforcement by declaring it as abstract. Notice if I get rid of it, no, now we're not enforcing anything. We're just creating a method like we did before.

behavior, and I create that enforcement by declaring it as abstract. Notice if I get rid of it, no, now we're not enforcing anything. We're just creating a method like we did before. Abstract means all child classes must implement this behavior. And trust me, if you don't think that's useful, it actually is. If you're working with somebody else's code or your own code that you wrote a year ago, you may not remember that you have to implement this method. But because it is declared as abstract, your editor and the language itself is going to enforce that behavior. So, now, yeah, I'm in phpStorm, and I can even have it create that method stub for me, just like that. Cool. So, now, if I create another version, why don't we, what's one of our achievement badges? I think we have one that's like talkative. So, this is somebody who really participates in the forum a lot. I can't remember what it's called, but I'm just going to call it talkativeAchievements.

I think we have one that's like talkative. So, this is somebody who really participates in the forum a lot. I can't remember what it's called, but I'm just going to call it talkative achievements. All right, let's extend from the parent class. And now, oh, I see here I need to add some missing behavior, qualifier. And now this one, yeah, maybe this inspects the user's forum participation. So, maybe that's represented by comments. And we're going to check if their commentCount is greater than or equal to 200, or whatever arbitrary threshold you declare. All right, so now we have multiple subclasses that inherit behavior and qualities and characteristics, even properties, from a parent. Okay, so a lot to cover there. It's okay if it's confusing. Watch the video again if you need to. And be sure to ask questions below this video. And of course, if you're subscribed to Layercast, take the exam. It really helps.

Watch the video again if you need to. And be sure to ask questions below this video. And of course, if you're subscribed to Layercast, take the exam. It really helps.

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟