3 Reasons to use Interfaces in Object Oriented Programming

Although this is primarily a PHP/WordPress blog, this article should be instructive for most programming languages that support Object Oriented Programming. My hope is that it helps you decide to use Interfaces when writing your programming languages. Ultimately, this will help you write better code for yourself and for other developers.

Why use interfaces when writing Object Oriented code?

1. Better documentation

If all of your classes implement interfaces, your interfaces can contain documentation. If you use doc blocks for commenting and automatic documentation, this actually helps to generate comments on classes. Better still, interfaces create a set of instructions that are action-agnostic that allow programs to know exactly what kind of parameters are being requested and, in PHP 7+, exactly what kind of return value is going to be received. Documentation is an incredibly powerful feature that makes interfaces worthy of use all by themselves. But we aren’t done yet… It gets better.

2. Powerful way to conditionally inject dependencies

If you’re using Dependency Injection in your code, then interfaces make your job considerably easier. Because you can implement multiple interfaces on a single object, you can easily add a “UserInterface” with the methods setUser and getUser. In the back-end, you can set up a Factory like so:

class MyFactory
{
    private $user;

    public function __construct(User $user)
    {
        $this->user = $user;
    }

    public static function getClass($classname)
    {
        $class = new $classname();

        if (!($class instanceof FactoryMember)) {
            return null;
        }

        if ($class instanceof UserInterface) {
            $class->setUser($this->user);
        }

        return $class;
    }
}

Crucially, this factory does not need to know whether a class has the UserInterface until it creates it. That means that this factory can store any class and auto-magically inject whatever is required.

3. Compatibility checking

If you take a look at the above code, you’ll see an additional interface, FactoryMember. In my example, I wanted to only create classes that implemented a FactoryMember interface. What’s in this interface? That’s up to you. There are cases where such an interface is blank, and you simply want to make sure that a class implements it for compatibility reasons.

In this case, you can think of an interface as also being an attribute of a class. Lets say you have Pet as a base class, with Cat and Dog as child classes. Here are some additional interfaces:

interface Furry {}

interface Playful {}

interface Shy
{
    function run();
}

Of the three interfaces above, only Shy has a method. That’s OK. Ultimately, these are attributes that help to describe pets. Now, you can write a custom message depending on the interfaces that an object has:

$dog = new Dog();

$msg[] = "You see a dog.";

if ($dog instanceof Furry) {
    $msg[] = "There's hair everywhere.";
}

if ($dog instanceof Playful) {
    $msg[] = "The dog's tail is wagging.";
} elseif ($dog instanceof Shy) {
    $msg[] = "The dog is shy and runs away!";
    $dog->run();
}

echo implode(" ", $msg);

Just like that, you’ve used interfaces to help you create a description of a dog. While you could implement each description as a method ($dog->getPlayfulMessage(), $dog->getShyMessage(), etc.), that may not always be desirable. If the messages change based on a situation (maybe when you pass a groomer, for example), then the interfaces can be a very quick way to determine attributes, and a compelling alternative to something like $dog->hasAttribute('hairy') when you’re building an application and don’t know how many methods you might want to call conditionally based on the attribute (aka, run for the Shy interface.

Conclusion

Programming with interfaces is not just a “best practices” convention. Like most best practices, it has a solid payoff for the developer who is willing and able to implement them. It not only allows for better documentation, but it also allows for more flexible use of design patterns and more inter-operable code. Finally, it enables a user to attach custom attributes that can grow with the application. For a little extra work at the beginning, interface programming will reap dividends as your codebase matures.

Leave a Reply