11

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);
kero
  • 10,647
  • 5
  • 41
  • 51
user702300
  • 1,211
  • 5
  • 22
  • 32
  • 1
    Interfaces and Abstracts are totally different things with totally different purposes, so you can't really compare them in this way – Mark Baker Dec 07 '13 at 00:07
  • 1
    I can see the differences but can't really understand the difference in practical sense :( Because both of them works if I want to inherit from one Interface? Although it can implement from more than one Interfaces, correct? Thanks! – user702300 Dec 07 '13 at 00:26
  • My bad i pasted wrong code for second example – Roman Toasov Oct 31 '16 at 00:01

3 Answers3

9

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');
    }
}
nihylum
  • 542
  • 3
  • 7
2

Really abstract classes and interfaces are different.

Consider an interface as a contract, it lays out the rules that other classes (which implement it) must follow.

Abstract classes on the other hand are more like starting points, which other classes can build on, hence why they are sometimes called base classes.

------- Edit with example

I'm not an expert on such things, but I've always just done interface -> class.

For example, here is a simple interface:

interface AnimalInterface {

  public function all();

  public function findBySlug($slug);

}

And here is the class which implements that interface (simplified):

class AnimalEloquentRepository implements AnimalInterface {

  public function all()
  {
    return Animal::all();
  }

  public function findBySlug($slug)
  {
    return Animal::whereSlug($slug)->first();
  }

}

I do often have a base class, which others extend, but I've only once used an abstract class in a real world app, and that ended up getting replaced.

I'm sure there are better ways to do things, but this has worked really well for me in the past.

Tom Green
  • 373
  • 4
  • 18
  • But based on the examples above, which one would you follow and why? – user702300 Dec 07 '13 at 00:24
  • I've amended my answer with a real world example that I use. – Tom Green Dec 07 '13 at 00:34
  • Okay, thank you for the example, what about defining the __construct() in Interface? Does it make sense to enforce it to pass the parameter variable like: public function __construct($connection); – user702300 Dec 07 '13 at 00:37
  • It depends on your situation, obviously if you've got a class which requires the $connection variable then you could define this using the interface. Personally I wouldn't because I mainly use __construct() for dependency injection. – Tom Green Dec 07 '13 at 00:40
  • [Here's an old stackoverflow answer to this same question. I found it very informative.](http://stackoverflow.com/a/479168/2171102) – echochamber Dec 07 '13 at 00:47
0

My reputation doesn't allow comments, but this statement in tr0y's answer is misleading:

"Abstract classes defines an interface that must be implemented to the heirs of the abstract class."

One of the main differences between an interface and an abstract class is that you are not required to implement any of the methods of an abstract class in a class that extends it. It's quite common for the abstract class to have methods with default behavior and only provide those methods in the heirs if the default behavior is not what you want.

On the other hand, you are require to create all methods specified in an interface in any class that implements that interface.

Another difference is that methods in an interface cannot have a body, while methods in an abstract class must have a body.

Bob Ray
  • 1,105
  • 10
  • 20