At this point, I’d say that the foundations of understanding object-oriented programming have been laid.
Specifically, I’ve covered:
And, yeah, there’s some debate as to what constitutes the foundations (that is, some don’t toss polymorphism into the mix though I do). But the above four should provide a solid foundation off of which to continue building your object-oriented programming skills.
There are more, but I don’t think they are as deep, detailed, or tough to understand as some of the aforementioned concepts. Then again, different things come easier to others.
At any rate, the next two topics that are important to understand are:
I’ll talk about each separate but make sure that you’ve read the Fundamentals series first because the above two topics will allow you to rely on them and take advantage of them.
Vague, I know, but let me explain and then go from there.
By far, the most common definition of an interface that you’re likely to hear is that it’s a contract. This isn’t wrong, but I think it leaves a lot to be desired.
For example, when you think of contracts you likely think of something that’s very involved, lots of jargon, a complicated process of getting something signed, dated, ready to work and do so on.
But when it comes to programming interfaces, this really isn’t the case. In fact, I’d argue that defining interfaces can make programming easier and it alleviates a lot of red-tape because it makes things very black or white as to what something should implement.
A Word About “Interfaces”
Our industry uses the word “interface” for two things:
- Designers and users use the term interface to describe what they see and how they interact with the application. This includes things like buttons, dropdowns, and other elements that we can “touch.”
- Programmers use the term to refer to what functions a subclass must implement to adhere to an interface. This is called “programming to an interface.”
The latter is what’s going to be discussed in this article. And no, we’re not going to use typical examples like programming to an Animal interface or whatever. Instead, we’ll look at doing so from actual code samples.
Programming to an Interface
We define “programming to an interface” as a way for us to write code that implements the signatures of functions defined in said interface.
But what are method signatures? Simply put, method signatures include:
- the name of the name of the function,
- the arguments it takes,
- the visibility modifier
In the context of a class, you will see it like this:
In the code above, we can see that the set function accepts a key and a value that will be used and the function is accessible by any object that has a reference to the class.
But interfaces can also include this. There’s a caveat, though: Interfaces have no method implementation.
So rather than somthing like this:
You’ll see this:
But there’s also a couple of sublties to note in the code above.
- This code does not define it as a class. Instead, it calls it an interface.
- The class name is prefixed with an ‘i’ to indicate it’s an interface. This isn’t required; it’s a convention.
- The method has no implementation. It has nothing but a signature.
When we create an interface, we’re saying, as mentioned above, that whatever class implements the interface is going to define the methods it includes.
So if we were to tie everything together that we’ve seen above, the final implementation would look like this (though we’d ideally keep this in separate files):
And that’s how interfaces and classes fit together.
In simple terms, yes. But in my experience, I’ve found that there’s more to it than simply defining the methods and implementing them.
Often, it’s easy to define classes, then define the interface, then implementation the interface. But that’s completely backward. Instead, we need to think more strategically about our work.
Rather than backing into an interface, which completely defeats the purpose, we need to start broad so that our classes can specialize in what they do all the while implementing functionality that’s common not only to that class but other classes that may need the same functionality.
Using the example above, we may have a SimpleCache a TransientCache or some other type of cache. Regardless of which type of cache we implement, they’ll implement the interface, and the functionality will be left to the class implementing the interface.
So we define what a cache might look like at a high-level, but the implementing classes will define exactly how they function.
If you’re a WordPress developer and you’re looking to learn how to build things on top of the application using practical, object-oriented techniques, then why not join the site?