BACK

Tutorial: PHP Abstract Class Vs Interface – Step By Step Guide

Before talking about the main differences between PHP Abstract Class vs Interface, let’s make it clear on how they work.

What is PHP Interface?

PHP interface defines which methods a class must perform. In other words, it is a class promise or agreement to implement the same public methods.

You can define an interface in the same fashion as a class, but with the interface keyword. For example, this is how an empty interface might look like:

interface Template {

}

Inside the interface, we usually define empty methods. However, we can also specify a constructor that must be implemented by the class, too. For example, this how Template interface might look like in the imaginary project:

interface Template {

  const ACCESSIBLE_BY = 'administrator';

  public function __construct(array $data, int $postId); 
  // Must be implemented with the same signature

  public function getTitle(): string;
  public function getBody(): string;
  public function publish(): void;

}

A class that implements the Template interface has to define the same methods. For example, defining an empty Page class that implements Template interface:

class Page implements Template {

}

will result in a PHP Fatal error: Class Page contains 5 abstract methods and must therefore be declared abstract or implement the remaining methods (Template::__construct, Template::getTitle, Template::getBody, …) in C:\Users\Work\Code\test.php on line 15.

To solve this issue, we must implement all of the missing methods. For example:

class Page implements Template {

    private $postId;

    public function __construct(array $data, int $postId) {
        $this->data = $data;
        $this->postId = $postId;
    }

    public function getTitle(): string {
        return $this->data[$this->postId]['title'];
    }

    public function getBody(): string {
        return $this->data[$this->postId]['body'];
    }

    public function publish(): void {
        $this->data[$this->postId]['publish'] = true;
    }
}

Note: return types must match, otherwise you will result in another PHP Fatal error: Declaration of Page::getTitle() must be compatible with Template::getTitle(): string in C:\Users\Work\Code\abstract_vs_interface.php on line 14

Also, please note that interface constants can’t be overridden:

class Page implements Template { 

    const ACCESSIBLE_BY = 'manager'; // Can't be overridden!

}

This will result in another PHP Fatal error: Cannot inherit previously-inherited or override constant accesibleBy from interface Template in C:\Users\Work\Code\abstract_vs_interface.php on line 14

How PHP Abstract Class Works?

It’s hard to describe the abstract class in one sentence, but in simple words, I would call it a partially built class, that can have a fully implemented methods. For example:

abstract class Template {

     const ACCESSIBLE_BY = 'administrator';

     public $postId; 
     // Extended in the other classes. Doesn't work in interface.

     public function __construct(array $data, int $postId) { 
         // Extended in the other classes. Doesn't work in interface.
         $this->data = $data;
         $this->postId = $postId;
     }

     public function getTitle(): string { 
         // Extended in the other classes. Doesn't work in interface.
         return $this->data[$this->postId]['title'];
     }
}

class Page extends Template {

}

However, abstract classes can have abstract methods. Methods defined as abstract declare the method’s signature, and they can’t define implementation – similar to the interface that we talked about before. Also, constants defined in the abstract class can be changed, for example:

abstract class Template {

     const ACCESSIBLE_BY = 'administrator';

     abstract public function publish(): void; 
     // You must define this method, similar like in interface.

}

class Page extends Template {
    
    const ACCESSIBLE_BY = "manager"; // Can be changed
    
    public function publish(): void {
        $this->data[$this->postId]['publish'] = true;
    }
    
}

Also, it’s worth mentioning that the class defined as an abstract class can’t be instantiated:

$template = new Template(); // Won't work!

You will get this – PHP Fatal error: Uncaught Error: Cannot instantiate abstract class Template in
C:\Users\Work\Code\PHP\php-abstract-class-vs-interface\abstract.php:42

PHP Abstract Class vs Interface

#Abstract Class Interface
Keywordextendsimplements
DescriptionCan describe behavior and implement some of the functionalityDescribes the behavior of the class without any implementation
Constants Can be changed Can’t be changed

Properties 
AvailableUnavailable
Methods Complete and Incomplete Incomplete
Multiple Inheritance Unavailable Available
Access modifiers: public, private, protectedJust public and protectedJust public

Using Abstract Class and Interface Together

An example of how abstract class and interface might be used together:

$data = [
    1 => [  'title' => 'Home Page', 
            'body' => 'Lorem ipsum.', 
            'published' => false
        ],
    2 => [  'title' => 'Installing Laravel', 
            'body' => 'Lorem ipsum.', 
            'published' => true, 
            'comments' => ['1', '2']
        ]
];

interface TemplateInterface {
    public function __construct(array $data, int $postId);

    public function getTitle(): string;
    public function getBody(): string;
}

interface CommentInterface {
    public function getComments(): array;
}

abstract class Template implements TemplateInterface {

    const ACCESSIBLE_BY = 'administrator';

    protected $postId; 

    public function __construct(array $data, int $postId) {
        $this->data = $data;
        $this->postId = $postId;
    }

    public function getTitle(): string {
        return $this->data[$this->postId]['title'];
    }

    public function getBody(): string {
        return $this->data[$this->postId]['body'];
    }

    abstract protected function publish(): void;

}

class Page extends Template {

    const ACCESSIBLE_BY = "editor";

    protected function publish(): void {
        $this->data[$this->postId]['publish'] = true;
    }

}

class Post extends Template implements CommentInterface {

    const ACCESSIBLE_BY = "manager";

    public function getComments(): array {
        return $this->data[$this->postId]['comments'];
    }

    protected function publish(): void {
        $this->data[$this->postId]['publish'] = true;
    }
}

$page = new Page($data, 1);
var_dump($page->getTitle());

$post = new Post($data, 2);
var_dump($post->getComments());

Conclusion

If you are still not sure when exactly to use PHP abstract class vs interface, you can take a look at a more detailed example on this Github repository – I have included all of the above examples and more. Good luck!

References

Newsletter

Get my content to your inbox every Monday. I promise, no spam included!

.

Leave a Reply

Your email address will not be published. Required fields are marked *