Приглашаем посетить
Булгаков (bulgakov.lit-info.ru)

Section 8.17.  Interfaces

Previous
Table of Contents
Next

8.17. Interfaces

If you had a Boat class and a Plane class, how would you implement a Boatplane class? The methods found in Boat would be helpful to give you code such as sink( ), scuttle( ), dock( ), etc., and the methods found in Plane would be helpful to give you code such as takeoff( ), land( ), and bailout( ). What is really needed here is the ability to inherit from both the Boat class and the Plane class, a technique known as multiple inheritance .

Sadly, PHP has no support for multiple inheritance, which means it is a struggle to implement this particular scenario. The solution is to use interfaces , which can be thought of as abstract classes where you can define sets of abstract methods that will be used elsewhere. If we were to use interfaces in the above example, both boat and plane would be interfaces, and class Boatplane would implement both of these interfaces. A class that implements an interface has to have concrete methods for each of the abstract methods defined in the interface, so by making a class implement an interface, you are in fact saying, "This class is able to do everything the interface says it should." In essence, using interfaces is a way to form contracts with your classesthey must implement methods A, B, and C; otherwise, they will not work.

The above example could be written using interfaces like this:

    interface Boat {
            function sink( );
            function scuttle( );
            function dock( );
    }

    interface Plane {
            function takeoff( );
            function land( );
            function bailout( );
    }

    class Boatplane implements Boat, Plane {
            public function sink( ) { }
            public function scuttle( ) { }
            public function dock( ) { }
            public function takeoff( ) { }
            public function land( ) { }
            public function bailout( ) { }
    }

    $obj = new Boatplane( );

There are no access modifiers for the methods in the interface: they are all public by default, because it doesn't make sense to have them as anything else. Similarly, you shouldn't try to use abstract or static modifiers on your interfacesif you get an error like "PHP Fatal error: Access type for interface method boat::sink( ) must be omitted", you know you've gone wrong somewhere.

Try commenting out the bailout( ) method in the Boatplane class, so that it only has five methods as opposed to six. Now run the script again. PHP should quit with the fatal error, "Fatal error: Class Boatplane contains 1 abstract methods and must therefore be declared abstract (plane::bailout)".

Our Boatplane class, by implementing both the boat and plane interfaces, has essentially promised PHP it will have a method bailout( ). Therefore, PHP gives it one by defaultthe bailout( ) method from the plane interface. However, as interfaces and their methods are entirely abstract, and by commenting out that one line, we have not re-implemented bailout( ) in the Boatplane class. The abstract method will be used and will thereby make the entire Boatplane class abstracthence the error. What this has proved is that when a class implements an interface, it makes an unbreakable contract with PHP that it will implement each method specified in that interface.

Uncomment the bailout( ) method in the Boatplane class, and try commenting out both the Boat and Plane interfaces, as well as rewriting the Boatplane class so that you remove the "implements" part. This time the script should run fine, just as it did the first time around. Essentially, there is nothing differentthe Boatplane class has all the same methods as it did before, so why bother with interfaces at all? The key is the "unbreakable contract" aspect, because by having a class implement an interface, you know for a fact that it must implement all the methods specified in the interface and not just one or two.

The use of interfaces should be considered in the same light as the use of access modifiersdeclaring a property private changes nothing, really, except that it forces other programmers (and perhaps yourself) to live up to various expectations about the object of that class. The same applies to interfaces and, although they are perhaps likely to remain one of the more niche aspects of PHP, they are certainly here to stay.

Section 8.17.  Interfaces

There is one situation in which interfaces actually make a concrete difference to your code, and that's with the Standard PHP Library (SPL), which is a set of reusable interfaces and classes that solve basic programming problems. When trying to use functionality from the SPL, you must always implement the appropriate interfacesjust implementing the methods isn't good enough.


The function get_declared_interfaces( ) will return an array of all the interfaces currently available to you, and it takes no parameters.

If you really want to delve deep into the world of interfaces, you can also have one interface inheriting from another using the same syntax you would use to inherit classes. As a result, this next script is the same as the previous one, as the plane interface inherits from the boat interface, and the Boatplane class implements the Plane interface:

    interface Boat {
            function sink( );
            function scuttle( );
            function dock( );
    }

    interface Plane extends Boat {
            function takeoff( );
            function land( );
            function bailout( );
    }

    class Boatplane implements Plane {
            public function sink( ) { }
            public function scuttle( ) { }
            public function dock( ) { }
            public function takeoff( ) { }
            public function land( ) { }
            public function bailout( ) { }
    }

    $obj = new Boatplane( );

Section 8.17.  Interfaces

It's important to note that although interfaces can extend other interfaces, and classes can implement interfaces, interfaces cannot extend classes. If you try this, you'll get an error along the lines of "Fatal error: boat cannot implement dog - it is not an interface".



Previous
Table of Contents
Next