Traits vs Interfaces vs Abstract Classes in PHP

January 11th, 2022

You can use traits implement interfaces and extend abstract classes.
Here are some notes on how they are different and how to use them for better code design.


TLDR;

Use Interfaces as a Public Contract;
Use Abstract Classes as a Private Contract;
Use Traits as Class Extensions;
Traits will override abstract class methods;


Thinking in OOP

Here are some ways to think of traits, interfaces, and abstract classes to write better php—

Thinking Interfaces

  • Interface === Type
  • Use it to declare a public contract

It is a type, a new type of object. An abstract type.
It is similar to an abstract class but

  • You can implement multiple Interfaces but only extend one abstract class
  • Constants defined by an Interface are immutable (before PHP 8.1)
  • Interfaces can only have public methods and constants.
  • Interfaces cannot have properties. Abstract classes can.

It is not a contract, but we can make it a contract by pre-declaring its public behavior

Thinking Abstract Classes

  • Use it to declare a private contract

While Interfaces declare a public contract, abstract classes can declare a private contract

  • Use protected methods to decalre its private contract
  • Abstract classes cannot have private methods.

Thinking Traits

  • Traits are just like classes
  • Use it as class extensions

A trait can do anything a normal php class can do except

  • traits cannot define a constant
  • traits cannot extend another trait
Starting In PHP 8.0, Traits can now have abstract private methods.
Read more in this section

Extra notes on Traits

  • Methods in a trait are overwritable. You can change

    • the visibility (e.g. public to private)
    • the parameters
    • the return type
    • even the name
      use MyTrait {
          MyTrait::method as private differentMethodName;
          MyTrait::doSomething as public reallyDoSomething;
      }
      
  • All data/properties in a Trait are calculated at runtime

    • They are not compiled.
    • e.g. __CLASS__ will always be the class that is using the Trait.

Who wins?

Traits vs Abstract Classes

Trait methods will override methods in an Abstract Class.

trait MyTrait
{
    public function doSomething()
    {
        return 'trait wins!';
    }
}

abstract class MyAbstractClass
{
    public function doSomething()
    {
        return 'abstract class wins!';
    }
}

class MyClass extends MyAbstractClass
{
    use MyTrait;
}


$test = new MyClass();
echo $test->doSomething();
// This prints 'trait wins!'

New in PHP 8

Starting In PHP 8.0, Traits can now have abstract private methods.

  • These abstract private methods are not overwritable.
  • These abstract private methods can be used as contracts.
  • You cannot have abstract private in an abstract class.

Starting In PHP 8.1, You can override constants defined by Interfaces.