PHP: Interfaces

Interfaces are contract that ensures the availability of methods/actions that an object must contain. By implementing an interface, a class agrees to contain the definitions of the methods declared in the interface.

An interface is a contract, and if a class implements an interface, it agrees to provide the functionality declared in that interface.

Interfaces have just the declaration/signature of the method, and the classes(that implement the interface) have the definition of those methods.

If a class implements an interface, it must have definitions of all the methods declared in the interface.

We ensure the following by an interface-

By implementing one or more interfaces we ensure that the class has all the methods declared in the interface(s).
We can use the interface as the type of a method argument or object variable, and ensure that the argument/variable has the method declared in the interface.

Interface Capability/Rules

Here are some rules that we have regarding an interface-

Interfaces can do

Interfaces can contain method declarations(signatures of the methods).
All methods in an interface must be declared as Public.
Interfaces can contain constants.
All constants in an interface must be declared as Public.
A class can implement one or more interfaces(separated by commas).
A class can extend(inherit from) a parent class, and still can implement one or more interfaces.
An interface can be used as a type(for method argument or object properties).
An interface can inherit from one or more interfaces, by extending it.

Interfaces can not do

Interfaces can not contain the definition of the methods.
Interfaces can not contain private, or protected method declarations.
Interfaces can not contain private, or protected constants.
Interfaces can not contain properties.

Difference between Interface and Abstract Class

Sometimes we get confused while using an interface and an abstract class. Here are the differences that we need to keep in mind-

InterfaceAbstract Class
Interface can only contain method declaration.
Can not contain method body in any case.
Abstract class can contain method implementation.
(when the method is not declared as abstract)
Multiple interfaces can be implemented by a class.A class can extend only one Abstract class.
Interface can not contain methods declared with Private or Protected visibility.
All method declarations in an interface must be Public.
Abstract class can contain Private or Protected methods.
Interface can not contain property.Abstract class can contain properties(with Public, Private, and Protected visibility).
Interface can not contain a constructor or destructor.Abstract class can have constructor and/or destructor.

Interface Declaration

We can declare an interface by using the keyword “interface”.

Following is a valid interface declaration-

<?php

interface BigBoxInterface {
    
}

Add Method Declaration to Interface

All methods declared in an interface must be public.

Add function declaration to interface-

<?php

interface BigBoxInterface {
    public function myFunc(): void;
}

WARNING

If the method is not declared public then we get a Fatal Error with the message-

PHP Fatal error:  Access type for interface method 
BigBoxInterface::myFunc() must be public 
in test.php on line 4

Constant Declaration in Interface

Declare a constant in the interface if needed. Then constant must be public.

<?php

interface BigBoxInterface {
    public const MY_CONST = 76;

    public function myFunc(): void;
}

WARNING

If const is not declared as public then we get a Fatal Error with the message-

PHP Fatal error:  Access type for interface constant 
BigBoxInterface::MY_CONST must be public 
in test.php on line 4

Reflect on Interface

Let’s reflect on the interface to better understand what is the behavior of the elements of this interface-

<?php

interface BigBoxInterface {
    public const MY_CONST = 76;

    public function myFunc(): void;
}

$ref = new ReflectionClass('BigBoxInterface');

echo "isInterface: ";
var_dump($ref->isInterface());

echo "isAbstrace: ";
var_dump($ref->isAbstract());

echo "isInstantiable: ";
var_dump($ref->isInstantiable());

echo "Methods:";
var_dump($ref->getMethods());

echo "Constants:";
var_dump($ref->getConstants());

echo "Properties:";
var_dump($ref->getProperties());

Output:

isInterface: bool(true)

isAbstrace: bool(true)

isInstantiable: bool(false)

Methods:array(1) {
  [0]=>
  object(ReflectionMethod)#2 (2) {
    ["name"]=>
    string(6) "myFunc"
    ["class"]=>
    string(15) "BigBoxInterface"
  }
}

Constants:array(1) {
  ["MY_CONST"]=>
  int(76)
}

Properties:array(0) {
}

Interface Implementation in Class

Use the keyword “implement” to implement an interface for a class.
For the implementation we have to define all the methods declared in the interface.
All the methods must be public(as declared in the interface), so that these can be used by other clients.
<?php

interface BigBoxInterface {
    public function myFunc(): void;
}

class BigBoxClass implements BigBoxInterface {
    public function myFunc(): void {
        echo 'myFunc implementation in ' . __CLASS__ . PHP_EOL;
    }
}

// Demo
$bigBoxObj = new BigBoxClass();
$bigBoxObj->myFunc();

Output:

myFunc implementation in BigBoxClass

WARNING

The methods declared in the interface, must be defined in the class implementing the interface. If any of the methods is not defined then we get a Fatal Error, like below-

PHP Fatal error:  Class BigBoxClass contains 1 abstract method 
and must therefore be declared abstract 
or implement the remaining methods (BigBoxInterface::myFunc) 
in bigboxcode.php on line 9

Access Interface Constant

To access constant from an interface, use the following format-

InterfaceName::CONSTANT_NAME

Check the example below-

<?php

interface BigBoxInterface {
    public const MY_CONST = 76;

    public function myFunc(): void;
}

class BigBoxClass implements BigBoxInterface {
    public function myFunc(): void {
        echo 'myFunc implementation in ' . __CLASS__ . PHP_EOL;
    }

    public function printConst(): void {
        echo 'Value of MY_CONST: ' . BigBoxInterface::MY_CONST . PHP_EOL;
    }
}

// Demo
$bigBoxObj = new BigBoxClass();
$bigBoxObj->myFunc();
$bigBoxObj->printConst();

Output:

myFunc implementation in BigBoxClass
Value of MY_CONST: 76

Interface Method with Type

Declaration of a method in the class(implementing an interface), should match(be compatable) with the signature of the method in the interface.

This is true for all arguments and return types.

When we define the methods in a class for interface implementation, then-

Signature of the method should match.
Argument types must be compatable.
Return type must be compatable.
<?php

interface BigBoxInterface {
    public const FACTOR = 7.6;

    public function myFunc(): void;

    public function calculateTotal(float $rate, int $numberOfMonths): float;
}

class BigBoxClass implements BigBoxInterface {
    private const COEFFICIENT = 1.4;

    public function myFunc(): void {
        echo 'myFunc implementation in ' . __CLASS__ . PHP_EOL;
    }

    public function calculateTotal(float $rate, int $numberOfMonths): float {
        // Some calculation specific to this class
        $total = $rate * $numberOfMonths;

        $result = $total * self::COEFFICIENT / BigBoxInterface::FACTOR;

        return $result;
    }

}

// Demo

$bigBoxObj = new BigBoxClass();
$bigBoxObj->myFunc();

echo "Calculated total: " . $bigBoxObj->calculateTotal(540, 24) . PHP_EOL;

Output:

myFunc implementation in BigBoxClass
Calculated total: 2387.3684210526

WARNING

Signature of the method should match with the signature of the method declared in the interface. Else we would get an error like below-

PHP Fatal error:  Declaration of 
BigBoxClass::calculateTotal(float $rate, int $numberOfMonths): int 
must be compatible with 
BigBoxInterface::calculateTotal(float $rate, int $numberOfMonths): float 
in bigboxcode.php on line 18

Interface as Parameter Type

Interface can be used as type for parameters.
Object of class that implements the interface is eligable for that parameter.
<?php

interface BigBoxInterface {
    public function myFunc(): void;
}

class BigBoxClass implements BigBoxInterface {
    public function myFunc(): void {
        echo 'myFunc implementation in ' . __CLASS__ . PHP_EOL;
    }
}

// Demo

// Define a function
// that accepts an object
// of type BigBoxInterface(implements interface)
function myTest(BigBoxInterface $firstObj) {
    // Use the object passed in the param
    $firstObj->myFunc();
}

// Use the function
// We can pass an object of class BigBoxClass
// as it implements BigBoxInterface
myTest(new BigBoxClass());

Output:

myFunc implementation in BigBoxClass

Interface as Return Type

We can use the inrface as return types.
Object of a class implementing the interface can be returned, and considered as compatable with the interface return type.
<?php

interface BigBoxInterface {
    public function myFunc(): void;
}

class BigBoxClass implements BigBoxInterface {
    public function myFunc(): void {
        echo 'myFunc implementation in ' . __CLASS__ . PHP_EOL;
    }
}

// Demo

// Define a function
// that creates an object
// of type BigBoxInterface(implements interface)
function myTest(): BigBoxInterface {
    // Generate a new object of BigBoxClass
    // and return that for demo purpose
    return new BigBoxClass();
}

// Use the function
// We can return an object of class BigBoxClass
// as it implements BigBoxInterface
$testObj = myTest();
$testObj->myFunc();

Output:

myFunc implementation in BigBoxClass

Implementing Multiple Interfaces

We can implement multiple interfaces for a class.
We can just comma separate the names of the interface, to use multiple interface implementation for a class.
The class has to implement all the methods declared in all those interface, in that case.
<?php

interface IOne {
    public function myFuncOne(): void;
}

interface ITwo {
    public function myFuncTwo(int $first): void;
}

interface IThree {
    public function myFuncThree(): int;
}

class BigBoxClass implements IOne, ITwo, IThree {
    public function myFuncOne(): void {
        echo 'myFuncOne in ' . __CLASS__ . PHP_EOL;
    }

    public function myFuncTwo(int $first): void {
        echo '$first = ' . $first . ' in myFuncTwo in ' . __CLASS__ . PHP_EOL;
    }

    public function myFuncThree(): int {
        // Return some random value for testing
        return rand(0, 10);
    }
}

// Demo 
$bigBoxObj = new BigBoxClass();
$bigBoxObj->myFuncOne();
$bigBoxObj->myFuncTwo(43);
echo $bigBoxObj->myFuncThree();

Output:

myFuncOne in BigBoxClass
$first = 43 in myFuncTwo in BigBoxClass
8

Conflict in Implementing Multiple Interfaces

NOTE

If you are implementing multiple interfaces for the same class, and both has method with same name then the signature of the method should match(be compatible) in those interfaces.

There should not be any conflict between the method declaration in the interfaces if we want to use those interfaces for the same class.

<?php

interface IOne {
    public function myFuncOne(): void;
}

interface ITwo {
    public function myFuncOne(): int;
    public function myFuncTwo(int $first): void;
}

class MyClass implements IOne, ITwo {
    // public function myFuncOne(): void {
    //     $this->myFuncOneVoid();
    // }

    public function myFuncOne(): int {
        return $this->myFuncOneInt();
    }

    public function myFuncTwo(int $first): void {
        // Implementation for ITwo
        echo "myFuncTwo with int parameter: $first\n";
    }

    private function myFuncOneVoid(): void {
        // Implementation for IOne
        echo "myFuncOne with void return\n";
    }

    private function myFuncOneInt(): int {
        // Implementation for ITwo
        echo "myFuncOne with int return\n";
        return 42;
    }
}

$instance = new MyClass();
// $instance->myFuncOne(); 
$instance->myFuncTwo(10);

Output:

PHP Fatal error:  Declaration of MyClass::myFuncOne(): int 
must be compatible with 
IOne::myFuncOne(): void in bigboxcode.php on line 19

Extend Interfaces to other Interface

We can inherit from other interfaces to an interfaces.
Use the “extend” keyword for inheriting form other interfaces.
We can inheirit from multiple interfaces at the same time. We can just pass multiple interface names by comma separating it.
<?php

interface IOne {
    public function myFuncOne(): int;
}

interface ITwo {
    public function myFuncTwo(int $first): void;
}

interface IThree {
    public function myFuncThree(): int;
}

interface IMaster extends IOne, ITwo, IThree {
    public function masterFunc(): void;
}

class BigBoxClass implements IMaster {
    // public function myFuncOne(): void {
    //     echo 'myFuncOne in ' . __CLASS__ . PHP_EOL;
    // }

    public function myFuncOne(): int{
        echo 'myFuncOne in ' . __CLASS__ . PHP_EOL;
        return rand(1, 100);
    }

    public function myFuncTwo(int $first): void {
        echo '$first = ' . $first . ' in myFuncTwo in ' . __CLASS__ . PHP_EOL;
    }

    public function myFuncThree(): int {
        // Return some random value for testing
        return rand(0, 10);
    }

    public function masterFunc(): void {
        // method implementation here
    }
}

// Demo 
$bigBoxObj = new BigBoxClass();
$bigBoxObj->myFuncOne();
$bigBoxObj->myFuncTwo(43);
echo $bigBoxObj->myFuncThree();
$bigBoxObj->masterFunc();

Output:

PHP Fatal error:  Declaration of MyClass::myFuncOne(): int 
must be compatible with 
IOne::myFuncOne(): void in bigboxcode.php on line 19

Implementing Interface in Abstract Class

We can implement interface(s) for an abstract class.
We can choose to define the functions(declared in interface) in the abstract class.
We can also choose to not define a function(declared in the interface), in that case the function will remain abtract and we have to define it in the class exting the abstract class.
<?php

interface IOne {
    public function myFuncOne(): int;

    public function myCalculation(int $num1, int $num2): int;
}

abstract class BigBoxAbs implements IOne {
    // Implement only one of the methods for demo
    public function myFuncOne(): int {
        echo 'myFuncOne in ' . __CLASS__ . PHP_EOL;

        return rand(1, 100);
    }

    // Declare another abstract method 
    abstract public function absFunc(): void;
}


class BigBoxClass extends BigBoxAbs {
    public function myCalculation(int $num1, int $num2): int {
        return $num1 + $num2;
    }

    public function absFunc(): void {
        echo 'absFunc in ' . __CLASS__ . PHP_EOL;
    }
}

// Demo 
$bigBoxObj = new BigBoxClass();
$bigBoxObj->myFuncOne();
$bigBoxObj->absFunc();
echo $bigBoxObj->myCalculation(43, 88);

Output:

myFuncOne in BigBoxAbs
absFunc in BigBoxClass
131

Implementing Interface while Extending Parent Class

We can extend from a class, and implement inteface(s) for a class, at the same time.
<?php

interface IOne {
    public function myFuncOne(): int;

    public function myCalculation(int $num1, int $num2): int;
}

class BigBoxParent {
    // Implement only one of the methods for demo
    public function myFuncOne(): int {
        echo 'myFuncOne in ' . __CLASS__ . PHP_EOL;

        return rand(1, 100);
    }
}


class BigBoxClass extends BigBoxParent implements IOne {
    public function myCalculation(int $num1, int $num2): int {
        return $num1 + $num2;
    }
}

// Demo 
$bigBoxObj = new BigBoxClass();
$bigBoxObj->myFuncOne();
echo $bigBoxObj->myCalculation(43, 88);

Output:

myFuncOne in BigBoxParent
131

Predefined Interfaces in PHP

Here are some interfaces that are already built into PHP. These interfaces serve different purposes.

Here are those interfaces-

Iterator
IteratorAggregate
InternalIterator
Throwable
ArrayAccess
Serializable
Stringable
UnitEnum
BackedEnum

Leave a Comment


The reCAPTCHA verification period has expired. Please reload the page.