Using Interfaces in OOP in PHP
So, we have already found out that interfaces are a good way to control that all the necessary methods of a class are implemented.
Let's consider another, more practical, example. Suppose we have a class that will store an array of shape objects:
<?php
class FiguresCollection
{
private $figures = []; // array for shapes
}
?>
Let's implement the method addFigure
in our class for adding objects to the collection:
<?php
class FiguresCollection
{
private $figures = [];
// A shape object is passed as a parameter:
public function addFigure($figure)
{
$this->figures[] = $figure;
}
}
?>
Obviously, we assume that
an object with a shape will be passed
as a parameter to the method addFigure
.
However, there is no control over this!
Let's use a type hint and
explicitly specify the object type as Figure
:
<?php
class FiguresCollection
{
private $figures = [];
public function addFigure(Figure $figure)
{
$this->figures[] = $figure;
}
}
?>
Let's figure out what we have done.
If Figure
were a real existing
class, then we could pass objects of this class,
as well as its descendants, to the method parameter.
However, for us, Figure
is an interface.
In this case, the type hint means that
only objects of classes that implement our interface
can be passed to the method parameter.
Let's try to create an object of our class and add shapes to it:
<?php
$figuresCollection = new FiguresCollection;
// Let's add a couple of squares:
$figuresCollection->add(new Quadrate(2));
$figuresCollection->add(new Quadrate(3));
// Let's add a couple of rectangles:
$figuresCollection->add(new Rectangle(2, 3));
$figuresCollection->add(new Rectangle(3, 4));
?>
An attempt to add an object of any other class will result in an error:
<?php
$figuresCollection = new FiguresCollection;
class Test {}; // some other class
$figuresCollection->add(new Test); // will throw an error
?>
What does such control give us in practice:
since all shapes added to the collection
implement the Figure
interface, we can
be sure that each of them will have the method
getSquare
and the method
getPerimeter
.
Perhaps in the future, besides a square and a rectangle,
a triangle will appear, for example. In
this case, the triangle will also have
methods getSquare
and
getPerimeter
.
In practice, this gives us the following: we can
in the class FiguresCollection
make,
for example, a method getTotalSquare
, which finds
the total area of the shapes in the collection. In this method,
we will iterate through the array of shapes with a loop and
call the method getSquare
for each shape.
Since each shape implements the interface
Figure
, we can be 100%
sure that each shape will have
this method getSquare
.
So, here is the method implementation:
<?php
class FiguresCollection
{
private $figures = [];
public function addFigure(Figure $figure)
{
$this->figures[] = $figure;
}
// Find the total area:
public function getTotalSquare()
{
$sum = 0;
foreach ($this->figures as $figure) {
$sum += $figure->getSquare(); // use the getSquare method
}
return $sum;
}
}
?>
Without looking at my code, implement the same
class FiguresCollection
.
Add a method getTotalPerimeter
to the class
FiguresCollection
for finding the total perimeter of all shapes.