PHP Interface and Abstract Class best practice for inheritance?

user702300 picture user702300 · Dec 7, 2013 · Viewed 16.4k times · Source

When defining the structure and inheriting Interface and/or Abstract Class, which one is the best practice? And why? Here are 2 examples:

Here is the example for [Interface] -> [Abstract Class] -> [Class]

Interface DataInterface
{
    public function __construct($connection);
    public function connected();
    public function get();
}

Abstract class BaseData implements DataInterface
{
    protected $connection;

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


class UserData extends BaseData
{
    public function exists()
    {
        return is_connected($this->connection);
    }

    public function get()
    {
        return get_data($this->connection);
    }
}

$oUserData = new UserData(new Connection());

And here is the sample for [Abstract Class] -> [Class] without the Interface

Abstract class BaseData
{
    protected $connection;

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

    abstract public function connected();
    abstract public function get();
}

class UserData extends BaseData
{
    public function exists()
    {
        return is_connected($this->connection);
    }

    public function get()
    {
        return get_data($this->connection);
    }
}

$oUserData = new UserData(new Connection());

I am currently creating a small app (might grow larger) and confused on how to implement in the beginning correctly.

By the way, is this declaration for __construct() with parameter make sense in Interface?

public function __construct($connection);

Answer

tr0y picture tr0y · Dec 7, 2013

Abstract classes defines an interface that must be implemented to the heirs of the abstract class. An Interface-Construct defines an interface that must be implemented by a class that implements the interface-construct, the implementation of the interface is not limited to a single interface, whereas class inheritance is coupled to a single (abstract) class.

Interfaces in PHP are intentionally used to allow typehints of an limited subset of an entire class interface. There is no reason for an interface on abstract classes aslong their receiver of instances of their heirs did not use them ( with typehinting or logical identification over instanceof / is_a ). The more valuable benefit of interface-constructs are the possibility of replacing an common implementation of an interfaces with a alternate implementation.

In case of your BaseData-Example, i recommend to drop the abstract idea and use a trait and seperate interfaces instead.

trait connectionBrokerConstructor {
    protected $connection;

    public function isConnected()
    {
        return $this->connection instanceof Connection;
    }

    public function setConnection(Connection $connection)
    {
        $this->connection = $connection;
    }
}

interface connectable
{
    public function setConnection(Connection $connection);
    public function isConnected();
}

interface userDataRepositoryInterface
{
    public function get();
}

class UserData implements connectable, userDataRepositoryInterface
{
    use connectionBrokerConstructor;

    public function __construct(Connection $connect = null)
    {
        $this->setConnection($connection);
    }

    public function get()
    {
        return array('something');
    }
}