Classes and OOP (Part 4)

1.0 Previous Tutorial

This is the fourth tutorial in a series of tutorials on classes and OOP.

First Tutorial
Second Tutorial
Third Tutorial

In the previous tutorial we learned how to extend a class with either one child or with multiple. We also learned how we could dynamically use a variable to call on a certain class (doesn't necessarily need to be extending another class to call on a class this way).

1.1 Tutorial Introduction

In this tutorial, we would continue with extending classes but with a twist. Instead of simply extending a parent class, we are going to use an interface and implement it with a class.

As a reminder, in the previous tutorial we have left off with the following class. And instead of adding to it in this tutorial, we are going to change it up (you might want to save a back-up of this file for later if you are following along with the tutorial).

<?php
class fruit
{

    private $amount = 2;

    public function __construct()
    {
        echo "Picking up a(n) {$this->fruit}.<br />\n";
    }

    public function eat()
    {
        $this->prepare();
        $this->chew();
        $this->swallow();
    }

    public function amount($number)
    {
        if($number < 11)
        {
            $this->amount = $number;
        }
    }

    public function __destruct()
    {
        echo "We ate a total of {$this->amount} {$this->fruit}(s).<br />\n";
    }

}

class apple extends fruit
{

    protected $fruit = 'apple';

    protected function prepare()
    {
        echo "Washing the apple.<br />";
    }

    protected function chew()
    {
        echo "Biting the apple.<br />";
        echo "Chewing the apple.<br />";
    }

    protected function swallow()
    {
        echo "Swallowing the apple.<br />";
    }

}

class banana extends fruit
{

    protected $fruit = 'banana';

    protected function prepare()
    {
        echo "Peeling the banana.<br />";
    }

    protected function chew()
    {
        echo "Biting the banana.<br />";
        echo "Chewing the banana.<br />";
    }

    protected function swallow()
    {
        echo "Swallowing the banana.<br />";
    }

}

$fruit = 'banana';

$product = new $fruit();

$product->eat();
?>

2.0 Interfaces

An interface is pretty simple actually, and it does a lot of good when it comes to creating an expandable system (e.g: a system for modules... since you would be adding different modules).

Let me go a bit more into detail here to help you understand interfaces and the use of them before I show you how to create the interfaces and how to implement it within a class.

An interface is a point of interaction between classes. It's like a guideline of how classes that would implement it should look like. Implementing an interface is creating a contract between the interface and the class saying that the class will have all of the methods mentioned in the interface and extend on them.

An interface is not the same as a class and has a different role in OOP. It also does not behave like a class and is not used as a class. You can't initiate an interface like you would a class.

Interface is about keeping consistency within all of the classes that implement it, which makes adding classes to the system much easier to use (especially if they are called dynamically).

For instance you have a system which selects a module and runs the selected module. In order for you to use one code to run multiple modules, you need the modules to be created under guidelines which makes it possible to do so. This enables you to just add a class for that module and an option to the form (or a link, or however else you want to dynamically call on that class) and use that module without writing a whole lot more code to enable you to use that class.

Here is how an interface looks like.

<?php
interface fruit
{

    function __construct();

    function eat();

    function amount($number);

    function __destruct();

}

Looks weird, doesn't it? It doesn't define the methods or anything, what it does it tell the classes that implement it that they need to have those methods defined. Since it's an interface all of the methods in the interface are public. They cannot be protected or private, which means that in this case, all those functions that used to be either protected or private (in order to affect the usage of the class) are going to be defined in the class implementing the interface, but not set-up in the interface.

Here is how we would implement an interface.

class apple implements fruit
{

}

It's the same as extends (previous tutorial) except you use the keyword implements instead of extends. Here is how the apple class implementing the fruit interface would look like.

class apple implements fruit
{

    private $amount = 2;

    function __construct()
    {
        echo "Picking up an apple.<br />\n";
    }

    public function eat()
    {
        $this->prepare();
        $this->chew();
        $this->swallow();
    }

    public function amount($number, $size = 3)
    {
        if($number < 11)
        {
            $this->amount = $number;
        }
    }

    private function prepare()
    {
        echo "Washing the apple.<br />";
    }

    private function chew()
    {
        echo "Biting the apple.<br />";
        echo "Chewing the apple.<br />";
    }

    private function swallow()
    {
        echo "Swallowing the apple.<br />";
    }

    function __destruct()
    {
        echo "We ate a total of {$this->amount} apple(s).<br />\n";
    }

}

And if we run that.

$product = new apple();

$product->eat();

We would get.

Picking up an apple.
Washing the apple.
Biting the apple.
Chewing the apple.
Swallowing the apple.
We ate a total of 2 apple(s).

Here, you would notice that all of the functions that used to be defined in a parent class (in the previous tutorial) have being actually moved to the class implementing the interface. In the actual interface, they are just named and set-up, butthey are actually defined in the class.

Also take note of the function amount, mainly the fact that it takes an argument $number. If you would look in the interface, you would notice that the named and set-up function amount also has that argument in there. For every function named in the interface that has a required argument, that argument also needs to be present in the interface as well. Let's look at the following code.

public function amount($number, $size)
{
    if($number < 11)
    {
        $this->amount = $number;
    }
}

If we have this function in the class with the interface the way it is (with only 1 argument named) we would get an error because the variable $size is required (doesn't have a default value set). But if we make it optional than it is ok if the optional argument is not named in the interface (the following example is okay with the way our interface is right now).

public function amount($number, $size = 3)
{
    if($number < 11)
    {
        $this->amount = $number;
    }
}

Since $size has a default value set (making it optional) then it's okay when e have only 1 argument ($number) named in the interface. It would also be okay to name the argument $size in the interface and have it be optional in the class. (First set of code is the function named in the interface and the second set of code is how the function is implemented in the class).

function amount($number, $size);
function amount($number, $size = 3)
{
    if($number < 11)
    {
        $this->amount = $number;
    }
}

It is also ok if the argument names named in the interface are not the same as in the class implementing the interface.

function amount($number, $size);
function amount($number, $shape = 'round')
{
    if($number < 11)
    {
        $this->amount = $number;
    }
}

If we have a second class (banana for instance) we would have all those same functions found in 'apple' in 'orange'... especially 'construct()', 'eat()', 'amount()' and 'destruct()'.

class banana implements fruit
{

    private $amount = 2;

    function __construct()
    {
        echo "Picking up a banana.<br />\n";
    }

    public function eat()
    {
        $this->prepare();
        $this->chew();
        $this->swallow();
    }

    public function amount($number, $size = 3)
    {
        if($number < 11)
        {
            $this->amount = $number;
        }
    }

    private function prepare()
    {
        echo "Peeling the banana.<br />";
    }

    private function chew()
    {
        echo "Biting the banana.<br />";
        echo "Chewing the banana.<br />";
    }

    private function swallow()
    {
        echo "Swallowing the banana.<br />";
    }

    function __destruct()
    {
        echo "We ate a total of {$this->amount} banana(s).<br />\n";
    }

}

Which would display.

Picking up a banana.
Peeling the banana.
Biting the banana.
Chewing the banana.
Swallowing the banana.
We ate a total of 2 banana(s).

2.1 Extending Interfaces

We could extend in interface with a different interface if we wanted/needed to. For instance if we had an interface 'food' and we were extending that interface with 'fruit' so we would affect the way that our classes were written, we would do it the following way.

interface food
{

    function eat();

    function prepare();

    function chew();

    function swallow();

}

interface fruit extends food
{

    function __construct();

    function amount($number);

    function __destruct();

}

So we named the methods in food that we use in our main class (which are private) so now we need to change those functions in those classes ('apple' and 'banana') to be public instead of private. (Note, we also moved the location of function 'eat()' from interface 'fruit' to interface 'food'. Doesn't really matter.

2.2 Multiple Interfaces

If we ever want/need to, we could extend multiple interfaces by making a comma delimited list of all of the interfaces we are extending. For example (not adding with our tutorial example code).

interface apple extends food, product, item
{

    // ...

}

On top of this, a class implementing an interface can also implement multiple interfaces (instead of an interface extending an interface).

class apple implements food, product, item
{

}

2.3 Constants

Yes, we can have constants in our class. You would define them in the beginning of the interface (or class if you are just using a class without interfaces) and call on them as you would a static variable (without the dollar sign). For example (not used in our tutorial example code).

interface car
{
    const type = 'Hatchback';
}

And if you ever use a constant, you would call on it as.

echo car::type; // Would print 'Hatchback' (Without the quotes)

The difference between functions named in the interfaces and constants is that the constants are already defined in the interface, and you can't over-ride it in the class. The following class implementing the interface 'car' would throw you an error (as it is over-riding a constant).

class focus implements car
{
    const type = 'Coupe';
}

It would fail even if it is set to the same thing (If both interface constant and class constant of the same name are set to the same value).

3.0 Our File

At the end of this tutorial, our file should look like:

<?php
interface food
{

    function eat();

    function prepare();

    function chew();

    function swallow();

}

interface fruit extends food
{

    function __construct();

    function amount($number);

    function __destruct();

}

class apple implements fruit
{

    private $amount = 2;

    function __construct()
    {
        echo "Picking up an apple.<br />\n";
    }

    public function eat()
    {
        $this->prepare();
        $this->chew();
        $this->swallow();
    }

    public function amount($number, $size = 3)
    {
        if($number < 11)
        {
            $this->amount = $number;
        }
    }

    public function prepare()
    {
        echo "Washing the apple.<br />";
    }

    public function chew()
    {
        echo "Biting the apple.<br />";
        echo "Chewing the apple.<br />";
    }

    public function swallow()
    {
        echo "Swallowing the apple.<br />";
    }

    function __destruct()
    {
        echo "We ate a total of {$this->amount} apple(s).<br />\n";
    }

}

class banana implements fruit
{

    private $amount = 2;

    function __construct()
    {
        echo "Picking up a banana.<br />\n";
    }

    public function eat()
    {
        $this->prepare();
        $this->chew();
        $this->swallow();
    }

    public function amount($number, $size = 3)
    {
        if($number < 11)
        {
            $this->amount = $number;
        }
    }

    public function prepare()
    {
        echo "Peeling the banana.<br />";
    }

    public function chew()
    {
        echo "Biting the banana.<br />";
        echo "Chewing the banana.<br />";
    }

    public function swallow()
    {
        echo "Swallowing the banana.<br />";
    }

    function __destruct()
    {
        echo "We ate a total of {$this->amount} banana(s).<br />\n";
    }

}

$product = new banana();

$product->eat();
?>

3.1 Conclusion

In this tutorial we learned how to create an interface and how to implement it.

This page was published on It was last revised on

0

0 Comments

  • Votes
  • Oldest
  • Latest