PHP5 Abstracts and Interfaces, what's the difference?

Abstract

think of it as a way to share information across classes without actually creating a class. If you will never have a need for a particular class to be instantiated, yet want to provide members and methods that can be used by all children, use an abstract. In PHP we have only single inheritance, so your (child) class would just inherit (extend) from the abstract class.

Interface

An interface simply lists (function prototype) the methods a class must implement. However, in PHP a class can implement multiple interfaces and these interfaces can also be used in type hinting.

What's the difference?

On the surface, it sounds like interfaces are crippled abstracts. It is really how use use it. The analogy I've seen used to describe this is that classes (and abstracts) can be though of as nouns whereas interfaces can be thought of as adjectives. Consider this:
  • A Company has employees
  • Some employees are engineers
  • Some employees work executives
  • Some employees can hack the system
  • Some employees can take long vacations

  • You might define this like so:
    <?php
    // No company just has "employees", all employees have a particular function or belong to a group.
    // So, we don't want employee to be a concrete (one that can be instantiated) class.  Lets create an abstract.
    
    abstract class Employee
    {
        protected $employeeID='';
        protected $annualSalary=NULL;
        abstract protected function setEmployeeID();
        abstract protected function setAnnualSalary();
    
        public function getEmployeeID()
        {
            return $this->employeeID;
        }
    
        public function getAnnualSalary()
        {
            return $this->annualSalaryID;
        }
    
    } 
    
    //Now lets define some interfaces based on the description above
    //canHackTheSystem and canTakeLongVacations are the adjectives
    //they can be used to group employees in a manner that is different then just their job
    
    interface canHackTheSystem
    {
        public function getSecurityClearance();
    } 
    
    interface canTakeLongVacations
    {
        public function getHRApproval();
    } 
    
    
    // and now, finally our classes.  Notice the implements keyword to use interfaces
    
    class Engineer extends Employee implements canHackTheSystem
    {
        protected function setEmployeeID()
        {
    	//read from db, etc.
        }   
        protected function setAnnualSalary()
        {
    	//beg HR for a raise
        }
        //required by the interface 'canHackTheSystem'
        public function getSecurityClearance()
        {
    	//of course, they have all access
        }
    }
    
    class Executive extends Employee implements canTakeLongVacations
    {
        protected function setEmployeeID()
        {
    	//read from super-special db, etc.
        }   
        protected function setAnnualSalary()
        {
    	//definitely a large number
        }
        //required by the interface 'canTakeLongVacations'
        public function getHRApproval()
        {
           //all those bribes and gifts paid off
        }
    }
    
    //instantiate
    $engineer = new Engineer;
    $executive = new Executive;
    
    //ok, with these defined and instantiated, we can do cool stuff like this
    //a more applicable example might be if the object was instantiated via a Factory
    //but hopefully you get the idea.
    
    if ($executive instanceof canTakeLongVacations) {
        // schedule meetings during the winter months
    }
    
    if ($engineer instanceof canHackTheSystem) {
        // don't fire this person, they hold the keys to the kingdom
    }
    ?>
    
    So, the code above, we've defined an abstract that lets us create a partial blueprint for child classes along with shared members and methods that children don't need to define. We've also defined some interfaces that certain employee objects will implement if they are relevant. Finally, our code can reference those interface attributes (we're doing that with the instanceof keyword in this case) and make decisions based on their implementation of that interface. Pretty cool, huh? And that's just a simple example. Consider the definition of the Senior Engineer and you'll see that the sky's the limit:
    class SeniorEngineer extends Engineer implements canHackTheSystem, canTakeLongVacations
    {
       //she can do it all
    }
    

    So, hopefully this example demostrates the basic differences. You can learn about the nuisances and best practices for both (probably makes sense for your abstracts to implement interfaces themselves, for example) from the links below.

    IMO, if you're new to this concept and are not exactly sure how you will use it, you can skip the "Interface vs. Abstract" debate and just use abstract. You can use it just like interfaces (although you can only have one) and can use it for the shared code aspect as well.

    More Information:

  • http://www.sitepoint.com/forums/showpost.php?s=4534b667226b79f2cf32a69924f0f35a&p=2712450&postcount=5
  • http://www.php.net/manual/en/language.oop5.abstract.php
  • http://www.php.net/manual/en/language.oop5.interfaces.php
  • http://www.php.net/manual/en/language.operators.type.php

    Return to SuperTom.Com