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-
Interface Capability/Rules
Here are some rules that we have regarding an interface-
Interfaces can do
Interfaces can not do
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-
Interface | Abstract 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. |
NOTE
We have a full comparison of the Interface, Abstract Class, and trait.
Check the link below for a full comparison-
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
<?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-
<?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
<?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
<?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
<?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
<?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
<?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
<?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-