Lecture Notes - Week 14
- 26 - Introduction to Object Oriented Programming in PHP: pgs. 465 - 469
- Anything else you can find on Object Oriented Programming (especially Inheritance & Overriding)
Screencasts - Week 14
Outline of Topics
- Overriding Methods
- Thoughts on Class Design ( Is a vs. Has a)
In OOP, inheritance extends the behavior of one class (called the base or parent class) and reuses it as the basis of another class (called the sub or child class). Doing so allows for efficient reuse of code from a base class and is considered another central pillar of OOP. Another way to take advantage of inheritance is to design your base classes with the thought of more generalization and the sub-classes with more specificity.
This is best illustrated through an example. Let’s say we want to represent the idea of a pet:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
private) to make parent properties available to your sub–classes
Pet class will serve as our base class. If we want to create a more specific class with all the knowledge and methodology of a
Pet, we need to create a sub-class. We do that by defining our sub–class and extending the base-class using the keyword
1 2 3 4 5 6
Since we are extending the
Pet class, don’t forget to include it before declaring our sub-class.
Now let’s add more specific functionality to our sub-class:
1 2 3 4 5 6 7 8 9
Let's create another sub–class:
1 2 3 4 5 6 7 8 9
Here's how we might use these classes:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
You’ll notice that I include a reference to the
Petclass even though
Catalso include the
Petclass. It is a best practice, as long as I am instantiating an object of a base class to include the base class, even though an instantiated sub-class inherits the base class as well. The reason is, I would minimize any breaking changes if the inheritance structure were to be redesigned. Remember to use
require_onceso you don’t get a fatal error when including a class that already exists.
And here is the output:
With inheritance, I can create more specific data and methods based on the details in my sub-class. However, I don’t like that my dog and cat are portrayed as exercising the same way. It would be handy to customize or override the different ways my dog and cat exercise.
Another central pillar of OOP is the ability to override the behavior of methods based on the specificity of the subclass. In fact, with the ability to override methods, we don’t have to keep track of which specific method to use. We can rely on each subclass taking care of its unique details for how something is done. It is done automatically for us based on the subclass type. This behavior is called polymorphism (meaning many forms), another main pillar of OOP.
We override the behavior of a base class’s method by redefining it in the sub-class. The rule is: the method in the subclass must have the exact same signature as the method in the base class.
Here is the
Dog class with
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Here is the
Cat class with
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
A powerful feature of OOP is we don’t have to make any changes to code that uses the
Cat class since we call the methods the same way. Just rerun it and notice the change in the output:
Thoughts on Class Design
Now that you're armed with the knowledge of basic class creation, inheritance, and overriding, you have some good tools available to you for how you design your classes. Let's take a simple example of modeling a house in software. For example, let's say we have a house with three rooms in it: a bedroom, bathroom, and kitchen. And let's just focus on one of these rooms: the bathroom. A bathroom is a room, and a bathroom has things like a sink and toilet in it.
The Is a vs. Has a Test
This is known as the Is a vs. Has a test. Specifically, it tests the relationship between two things. When designing classes, you ask the question: Is a bathroom a room. You also ask the question are all rooms bathrooms. If the Has a question passes, (usually) only one of these questions will be true. This will give the directionality of the inheritance relationship. Which means
Room will be the base or parent class of
Bathroom. Let's ask the Is a question again of the relationship between a bathroom and a sink: Is a bathroom a sink? No. Is a sink a bathroom? No again. Therefore the relationship between a bathroom and a sink fails the Is a test and is not a candidate for inheritance. Next let's move on to the Has a test. So, then we ask the question: Does a sink have a bathroom? No. Does a bathroom have a sink? Yes! In the same way as the Is a test, we ask the Has a test both ways to establish directionality. Since we pass the Has a test: A bathroom has a sink, we can make a
Sink object a property of the
Bathroom class. This is known as Composition.
There is a lot more to proper class design, however the Is a and Has a test is a foundational principle that will give you a lot of mileage as you're thinking about how to design your classes