Lecture Notes - Week 14
Readings
- Chapters:
- 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
- Inheritance
- Overriding Methods
- Thoughts on Class Design ( Is a vs. Has a)
- Demonstration
Lecture
Inheritance
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 |
|
NOTE: Use
protected
(notprivate
) to make parent properties available to your sub–classes
The 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 extends
:
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
Pet
class even thoughDog
andCat
also include thePet
class. 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 userequire_once
so you don’t get a fatal error when including a class that already exists.
And here is the output:
Overriding Methods
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 excercise()
overridden:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
Here is the Cat
class with excercise()
overridden:
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 Pet
, Dog
, and 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