When I started this series, I talked about the four pillars of object-oriented programming. Each of these topics is listed and linked below.
At this point, I’d normally want to begin moving on to the next topic. Before doing so, though, I’d like to spend one more post exploring the concept of polymorphism.
In my career, thus far, I’ve seen few topics give those getting into object-oriented programming more confusion and problems than polymorphism. So I’d like to discuss it a little more in-depth within the context of object-oriented programming and outside any particular framework or application (like WordPress).
In this post, I’ll do a quick review of what we’ve discussed thus far, then hop back into polymorphism.
First, as mentioned, I want to quickly review what’s been discussed so far especially if you’ve glossed over any of the previous posts.
Don’t worry: Nothing below digresses into code. Instead, it simply defines the terms we’ve used so you have some idea as to what I’m referring to whenever you see the word crop up throughout this series.
We abstract the idea of something into a class. Instead, we’re going to be abstracting ideas into their classes. And there’s a key idea here: A class should represent a noun.
Encapsulation is really just a “big” word that refers to the idea of managing its responsibilities (or keeping track of its data).
Inheritance refers to the idea that one class, although it has its own implementation, literally inherits properties, functions, and general implementation from a parent class.
Polymorphism allows us to refer to a class of one type when it may be declared as another type.
With that said, this is where I think things can get a little more complicated. In the previous posts, I’ve provided a number of different code examples (and I urge you to look back at them).
But in today’s post, I’m going to try to explore the idea a little bit further both in explanation then in code.
Relating To Inheritance
If it’s not evident at this point, polymorphism is highly related to inheritance. Think of it this way: If one class inherits properties and methods from another class, then it can “stand in place” of the parent class.
That means if you have something like a Content class and then you have two subclasses, one being a Post and one being a Page, you can instantiate the class by using the Content reference type.t
But at runtime, it will actually be an instance of the Post type. Make sense? Here’s some code as an example.
First, we’ll start with defining a Content class:
It has the general properties that you’ve likely come to expect – title, content, and metadata. Granted, these properties are just strings but they could be more elaborate data structures in a real-world situation.
Now let’s look at a Post:
What happens, then, if you call a method on the Post class, like getTitle, that doesn’t exist but it does exist in the Content class? Then because of inheritance, it will look for the method in Post, not find it, then begin looking for it in Content.
If it’s found, it’ll run it.
Similarly, we can do something like this with the Page class and content data. First, we instantiate the base class then we set properties specific to the Page. In this case, it’s going to be a category.
Now when we run the code, we can start with the Content:
Notice that this looks like we’d expect since we have a title and we have content. Let’s also look at the Post:
This works because we have an author but we also have a title because it resides in Content. But if we try to call getAuthor on an instance of Post?
We’re going to get an error because the method doesn’t reside in that class.
So what are we to do? Since we don’t have strong types in PHP, we can’t cast it to a different type.
There are design patterns for this, which I’ll be discussing in a future set of posts, but PHP does not allow for this as easily as some other languages (like C# or Java).
Questions About Polymorphism
Hopefully, the above code gives you an idea as to how a concrete type such as a Post or a Page can implicitly have the properties and methods of its base class, Content, used at runtime.
But it also raises a few questions, doesn’t it? For example:
- Why is Polymorphism Useful? Ultimately, it’s a matter of flexibility. That is, you can write a generic Content type but then create a Post or a Page as we’ve seen above. This then gives us all the benefits of the Content class while also giving us the specificity of the Post class, for example.
- This seems to be more confusing than flexible. In a way, it’s confusing because the code requires a bit of tracing. That is, you might start in the Post class and have to look up to what the Content class offers. On the flipside, it also makes it really easy to introduce a new Content subclass and then use it when it’s best suited at runtime.
As far as referring to superclasses and subclasses, this is where having a solid IDE comes into play.
It’s always nice to have an editor that you like, sure, but having one that can intuitively determine what’s the parent class, what’s the base class, etc., can go a long way in helping to trace, debug, follow, and write new code.
But that’s content for another post that will come after we talk about design patterns.