Defining Encapsulation0:00
All right, your next keyword is encapsulation. And yet again, it's kind of a scary term, so let's break it down. All right, so the real-life definition of encapsulation is something like to enclose within a capsule, right? So if that's all we knew, we could sort of parse what it probably means within the context of programming, right? So enclose, all right, to hide, to contain, to conceal, to tuck away, cool. Capsule in this case just refers to like a container. All right, so we are hiding something from the outside world. We are storing it within a container where it is concealed or enclosed from the outside.
All right, so we are hiding something from the outside world. We are storing it within a container where it is concealed or enclosed from the outside world, meaning the outside world doesn't have access to it. And you know what? In a programming context, that's basically it. So let's have a look here. Now, the programming-specific definition of encapsulation might be something like this. Restriction of access to an object's internals. All right, so here's the example I'm going to show you, at least to start. And once again, it's this dreaded Person class.
Person Class Example1:10
All right, so here's the example I'm going to show you, at least to start. And once again, it's this dreaded Person class. Why do we always reach for it when you never encounter it in a real code base? And the answer is, it's just a great way to visualize things in your head. First we use a real-life example, and then we translate it into a more programming-specific example, which we'll do later in the video. All right, so imagine we have a person named Bob. New Person, and I'm going to pass through his name right here. All right, so now we have Bob. Let's make sure we accept his name in the constructor, like this, public string name.
All right, so now we have Bob. Let's make sure we accept his name in the constructor, like this, public string name. Cool. So now if we var.Bob and we give this a run, give it a run, and of course we get a Person object where the name is set to Bob. All right, so we could say effectively that this Person is exposing its name to the outside world. And that makes sense, right? Hey, how are you? What's your name?
Hey, how are you? What's your name? My name's Bob. Right? Bob is exposing his name to the rest of the world, right? He doesn't conceal it. Now what else might he expose? Well, how are you, Bob? What do you do for a living, all right? He might expose his job to the outside world.
What do you do for a living, all right? He might expose his job to the outside world. What else? Maybe Bob has a Steeler's head on and he's exposing his favorite sports team. So we might have favorite team or something like that. That's another thing that Bob may want to expose to the outside world. However, there's other things that we all know we don't expose to the outside world. All right, so what is something that Bob might keep to himself? I don't know. Some kind of medical, embarrassing medical condition he doesn't want you to know about.
I don't know. Some kind of medical, embarrassing medical condition he doesn't want you to know about. Maybe even something like his anxieties or his worries or things that keep up at night. Things that keep Bob up at night. He's probably not exposing to the outside world, right? Maybe he just thinks about dying all night long. He's worried about it. He's scared of it. He doesn't know what's going to happen, right? Those are things that Bob feels and represent Bob, but also things that Bob doesn't really
He doesn't know what's going to happen, right? Those are things that Bob feels and represent Bob, but also things that Bob doesn't really expose and advertise when he goes to work or hangs out with his friends. All right, so now we can see there's sort of a distinction here, right? We might call these part of Bob's public interface. It's what he reveals to the world. I'm Bob. This is my job. This is my favorite team. These are my kids, right?
This is my favorite team. These are my kids, right? And then there's other things that are encapsulated or concealed from the outside world, and that would be the medical condition or the things that keep Bob up at night. Okay, so why don't we just say, return, and I'm just going to hard code this. Bob is afraid of dying, okay? I used this example in a course many years ago, and we're going to reach for it again just because it's so silly and dark. Silly and dark at the same time. Okay, so yeah, here's the problem.
Silly and dark at the same time. Okay, so yeah, here's the problem. Right now, on this object, I can call things that keep up at night, and of course, I know it's a silly example. Just come along for the ride. If we give it a run, sure enough, we can peek into Bob and we can see things that he does not want to share with us. All right, so how do we solve this problem? How do we ensure that the way Bob feels deep down and the things he does not want to share are not shared?
Using Visibility Keywords4:33
How do we ensure that the way Bob feels deep down and the things he does not want to share are not shared? Well, this is where visibility comes into place. We talked about it just a little bit earlier in the course. You'll notice that for all of our methods and all of our properties up until this point, we've declared the keyword, or visibility, public. And yeah, it's exactly what you think it means. It is publicly available to anyone who has access to this object. So in this case, name is public. That means I can access it like this, directly off of the object.
So in this case, name is public. That means I can access it like this, directly off of the object. So if we give this a run, of course, we get Bob. But now let's imagine that Bob is in a certain context where he just doesn't want you to know his name. He's in a witness protection program. Never thought I'd reference that in a Larikess course. But he's in a witness protection program and he can't reveal his name. All right, so we're going to update the visibility here. I'm going to say private or protected.
All right, so we're going to update the visibility here. I'm going to say private or protected. And we'll talk about the distinction in just a minute. We'll start with private. Now, if I can type, now, if I scroll down, you'll see, yeah, the name property has a red squiggly line here. And that's because we're trying to access it like it's publicly available to us. But it's not. It is concealed from us and it will be disallowed. If we give it a run, now I'm going to get a fatal error.
It is concealed from us and it will be disallowed. If we give it a run, now I'm going to get a fatal error. Cannot access private property name. All right, so if you think about it, this is really cool. We now have the ability via this keyword here to selectively decide which things we expose as part of our public interface and which things we tuck away. Things you don't necessarily need to see. All right, so let's bring this back to public. We're going to return. He's outside of the protection program now.
We're going to return. He's outside of the protection program now. And you can once again know what his name is. But right down here, the things that keep him or her up at night, mm-mm, we're not going to expose that to the outside world. We're going to change that to private. So now notice, if I were to try to access that method, it's not available to me. And just to make this crystal clear, if I bring it back to public, well, now it's part of the public interface. So it is available to me and I can see auto-completion here.
of the public interface. So it is available to me and I can see auto-completion here. So let's give it a run. php, of course, we peek into what Bob thinks about at night. But if we update the visibility to private, now, once again, we will get a fatal error. All right, so now what about the difference between private and protected? They're very similar with one distinction. Protected is a little bit more loose. And here's how I like to think of it. When you label something as private, that means it is private to me and me only.
And here's how I like to think of it. When you label something as private, that means it is private to me and me only. I don't share it with anyone, not even my wife or not even my kids, right? protected expands that bubble just a little bit. This is something that is protected between me and my family. Maybe, I don't know, maybe money is tough in your family and you tell your kids, guys, we can't go out to eat. Money is really tight right now. All right, that is information that is protected in your little family unit. But you probably don't go out to your friends or to your workplace and expose how rough
All right, that is information that is protected in your little family unit. But you probably don't go out to your friends or to your workplace and expose how rough money is for you right now. You know what I mean? Kind of a silly example, but it's kind of true actually. So we have some information that we reveal to everyone, some information that we share with just our family or our close unit, and then we have some information that is really private to us alone. And the exact same thing is true when it comes to your code base. Okay, so now we're done with the silly person example.
Real-World Code Examples8:09
And the exact same thing is true when it comes to your code base. Okay, so now we're done with the silly person example. Let's review some real life examples, or I should say real world examples. There's a difference there. All right, let's have a look. So I've now switched over to the LayerCast code base itself. So I can show you some real examples here. And why don't we start with my ReferralServiceProvider? Have a look here. All right, so this is a Laravel specific file provider that registers a component, our referral
Have a look here. All right, so this is a Laravel specific file provider that registers a component, our referral system with the framework. So let's have a look here at the visibility we've defined. We have a boot method that is set to public. So that means if you have an instance of this object, you can call boot on it. Great. No problem there. Next, we have a register method. And again, that is set to public.
Next, we have a register method. And again, that is set to public. If you have access to the object, you can call register. But then we have this method, store in session, and that is set to protected. However, it could just as easily be set to private. And you know what? In this case, maybe it's a little bit more appropriate. We'll talk about that more shortly. So two methods that are part of the public API, and one method that is really not part of the public API.
So two methods that are part of the public API, and one method that is really not part of the public API. So now your next question is, well, how do you determine what to reveal to the outside world and what should be concealed? And it's very simple. Just ask yourself, is this something that I should be able to access if I have access to the object? Or is it something that, I don't know, is rather unique to the implementation details, but not necessarily anything that you, as an outsider, need to know about? Let's have a look here.
but not necessarily anything that you, as an outsider, need to know about? Let's have a look here. In the boot method, we listen for when a route is matched. So this is like a User visits a page. We have calculated which route they're trying to load. Is it the home page? Is it the about page? In this case, we're checking, well, if the route's name is referral, then you accessed a referral-specific route, in which case we want to store some data in the session. All right, next, we call this method storeInSession, and then we pass through the relevant User.
a referral-specific route, in which case we want to store some data in the session. All right, next, we call this method storeInSession, and then we pass through the relevant User. And all that does is it tries to track down the relevant User, and if that person is subscribed, then we track the progress and conditionally award them a referral if the referred person signs up. But it doesn't matter. Don't worry about any of that. What I want you to think about is this storeInSession method, is there ever a reason to call this method from the outside world? And again, remember, when I say outside world, I mean this.
method from the outside world? And again, remember, when I say outside world, I mean this. If you had an instance of this provider, new ReferralsServiceProvider, is there ever a time when it would make sense to call storeInSession? No, right? storeInSession is very specific to the implementation of this class, but it's not anything an outsider would ever need to run or trigger. It's only something that will be triggered from directly within this class. So in those situations, there's no reason to muddy up the public interface. Again, think about this.
So in those situations, there's no reason to muddy up the public interface. Again, think about this. If this became public, well now, when I check the public API, of course, we're getting access to a lot of Laravel-specific methods, but sure enough, I'm now saying, yeah, this is something you can do with me, when it's really not. It's something I can do with me, and I will refer to it to execute the necessary logic, but it's not something you ever need to reference. So in those situations, make sure that you reach for either private or protected visibility. All right, so now, once again, how do we determine when it's private or when it's protected? And the answer is, well, it just sort of depends.
All right, so now, once again, how do we determine when it's private or when it's protected? And the answer is, well, it just sort of depends. Some people have preferred defaults, and some people have other preferred defaults, and that's just the way things work out here. Generally, a lot of people say default to private unless you have a reason to expand to protected. Others, and I would include myself in this second group, would say, you don't need to be so private. You can default to protected, and that means you can access the method if you're part of the class, or if you have a child that extends this class, they can access it as well.
You can default to protected, and that means you can access the method if you're part of the class, or if you have a child that extends this class, they can access it as well. That would be their preference, but it doesn't really matter. Just pick one and stick to it. And as always, you can tweak them whenever you need to, but yeah, I find it's easier to assume protected. Cool. Let's review one more example, and this one is where we validate an exam answer that you might provide. All right, so let me give you the quick 15-second gist as to what this code does.
might provide. All right, so let me give you the quick 15-second gist as to what this code does. You'll notice that as part of this course on the Larikast website, there are exams for each video. And when you submit an answer to one of those exam questions, yes, of course, eventually we execute that code securely, and then we check if you got the answer correct. However, before we do that, we perform an initial validation pass. It receives the answer that you provide, and it parses it, and then it inspects it for a number of things. Like, are there specific functions that you used that you shouldn't be using?
a number of things. Like, are there specific functions that you used that you shouldn't be using? Should you have imported a PHP class that you didn't import? Are you referencing superglobals? Are there forbidden functions? Are there functions you should be using but didn't use? All of that is contained within here, all right? So that's great. Now, I could say that the public API for this class is a run method. That's what we expose to the outside world, all right?
Now, I could say that the public API for this class is a run method. That's what we expose to the outside world, all right? But next, I can see a protected function called parse, and this creates a new instance of a ParserFactory class, and it parses the answer so that we can loop over it, inspect it, check what type is used, check what value is provided, things like that, okay? So what we can see here is this parse method was extracted for the sole point of readability. Now, if I come back right here, you can see I call that method as part of the run method. But yeah, it could just as easily have been inlined here. The only reason we extracted is, again, for readability. So with that in mind, there's no reason for us to use a public keyword here.
The only reason we extracted is, again, for readability. So with that in mind, there's no reason for us to use a public keyword here. It should be set to protected or private, because this exists for private reasons. It's not anything we need to expose to the outside world. All right, great. Next, as part of our public API, we have a getter. This often takes the form of get and then a property name. Now, we'll talk about this more in just a minute, but that might confuse you. Why do we create getters? Well, let's put a pin in that for just a minute.
Why do we create getters? Well, let's put a pin in that for just a minute. Next, we have four methods that we have here. And yeah, this is where we detect if you're using any forbidden function calls, if you're accessing super globals, if there are required functions you should use but didn't, and if there are imports you should have pulled in but didn't. Again, though, notice that the visibility is set to public. And this is where you have to ask yourself a question. And I'm going to tell you right now, maybe the answer is yes, and maybe the answer is no.
And I'm going to tell you right now, maybe the answer is yes, and maybe the answer is no. It just depends on what you want to expose. All right, so we ask ourselves the question, does it make sense for these four methods to be exposed to the outside world? If I have a validates answer object, should I be able to call these methods individually? And maybe the answer is yes, but likely the answer is no. This is really internal logic. And the only thing I want you to reference is, again, this run method that we defined up here.
And the only thing I want you to reference is, again, this run method that we defined up here. So if that's the case, again, update the visibility like so. Make it protected. If you anticipate child classes extending validatesAnswer, or if that will never happen, then feel free to label it private. It's up to you. Now we, again, have been very specific that these methods are unique to the internals of the class, but they're not anything that needs to be revealed to the outside world. Very cool.
Why Use Getters16:29
of the class, but they're not anything that needs to be revealed to the outside world. Very cool. So now let's scroll back up and finish up with a discussion around getters. When I was first learning about object-oriented programming, I was very confused by getters. Think about it. I would see an example. Actually, let's just clear all of this real quick. Let's just break it down. Nice and simple. All right, we'll even get rid of the docblock.
Nice and simple. All right, we'll even get rid of the doc box. So we're only focusing on the property and the getter. All right, so here's what I would see. They would label the property protected, but then they would have a public method, a getter, that would give you the value of that property. And I would always ask myself, all right, well, if I have, let's say, new ValidatesAnswer, if I have an instance of this class, why are you telling me that I can't access the property directly, but I can access a getter, which is going to return the value of the property? I couldn't wrap my head around this.
directly, but I can access a getter, which is going to return the value of the property? I couldn't wrap my head around this. What is the point? Or in other words, why not get rid of the getter entirely and just make this public? All right, well, here's the answer. In some situations, it's probably just fine to make it public. However, there are so many situations when you kind of handcuff yourself when you offer direct access to your properties. Imagine a situation where your property is public, but then a couple months later, something needs to happen before the value of that property is returned.
Imagine a situation where your property is public, but then a couple months later, something needs to happen before the value of that property is returned. Well, now you're handcuffed. What can you do? You're stuck. You would have to update every single reference where you access that property. And if you're building code that is used all around the world, you've broken everyone's code, right? Because now they're all going to have to update their individual code bases to reflect this important change that you need to make.
Because now they're all going to have to update their individual code bases to reflect this important change that you need to make. Imagine we have something like email and we'll have getEmail as a getter. All right, and I'm going to update this to example just to make it crystal clear. Well, if email was a public property, then yes, you could create your example and you could access the email directly. But then maybe we decide, no, when you get the email, it always needs to be masked in some way. And maybe you just need to replace the @ symbol with at. So replace @ with at or something like that. Well, if that is a rule that has been introduced into your company
So replace at with at or something like that. Well, if that is a rule that has been introduced into your company and everyone's accessing the email directly, think about it. What are they going to do? Everyone will now have to update their code to call your getter instead. So what many people prefer to do is always make their properties or just about always, most of the time, make their properties protected. And then for or in the situations where you need to access them, you can create dedicated getters. And that's a way of future-proofing your API.
you can create dedicated getters. And that's a way of future-proofing your API. If at any point you need to tweak what happens as part of fetching an email address in this case, now you have a hook of sorts to do so. You can access this method, make your change, and now everywhere in the world where somebody is calling this method, they will receive that change. See what I mean? So effectively, getters allow for more control and opportunity for validation and really backwards compatibility, right?
So effectively, getters allow for more control and opportunity for validation and really backwards compatibility, right? So that when we make changes, we have a place to perform that change without breaking everyone's code. And here's a good way to think of it. Public properties tie you to a specific implementation, while getters give you a stable interface that can evolve over time. All right, and that's going to do it, at least for this lesson. Now, of course, we got to dig further, but here's the last thing for now that I want you to take away from this video.
Now, of course, we got to dig further, but here's the last thing for now that I want you to take away from this video. When you hide internals by using those visibility keywords, like public, protected, private, when you hide internals, you are better protecting the consistency and integrity of your objects.
