Team LiB
Previous Section Next Section

Advanced Classes

Thus far, I have discussed in large part things that existed to one extent or another in PHP 4. In this and following sections, I'll introduce some of those new features to the PHP 5 object model that separate it from PHP 4.

Abstract Classes and Methods

As their name implies, abstract classes are used in OOP to define abstract objects. To understand what defines an abstract object, consider the concept of food. We all understand as people what "food" is, but have you ever specifically seen it? You have seen types of food (steaks, chicken, and so on) but the concept of food itself is an abstract conceptit exists only as a generalization of more specific things. This concept holds true to abstract classes as well.

In OOP, abstract classes are designed to provide a superclass that defines the abstract characteristics of classes that inherit from it. Abstract classes may or may not actually contain any code within them, and they can never be instantiated directly. Consider the example in Listing 13.15:

Listing 13.15. Using Abstract Classes in PHP 5
<?php
     abstract class Number {
          private $value;
          abstract public function value();
          public function reset() {
               $this->value = NULL;
          }
     }

     class Integer extends Number {
          private $value;
          public function value() {
               return (int)$this->value;
          }
     }

     $num = new Integer; /* Okay */
     $num2 = new Number; /* This will fail */
?>

In Listing 13.15, I have created an abstract class Number that is extended upon by the Integer class. Because the Number class is declared abstract, it cannot be instantiated. Looking at the Number class, we can see that two functions are defined: value() and reset(). In an abstract class, it is not necessary to provide any code for methods, although it can be included if desired. In the case of the Number class, because value() is something specific to a particular type of number, it is left to the child class to implement. To force this behavior on a developer writing code, the abstract keyword used to identify it has merely a placeholder in the Number class. This, however, is not true for the reset() method, which is consistent throughout any specific type of number.

NOTE

Abstract classes can be extended without implementing all the abstract methods defined within. That is to say, a child class must also be declared as abstract if it does not implement all abstract methods of its parent(s).


Interfaces

Unlike abstract classes, which provide a means to express abstract concepts in programming, interfaces are designed to assure functionality within a class. Specifically, interfaces are a means to define a set of methods a class claiming to implement that interface must have. To use interfaces, they must be declared with the interface keyword as shown next in Listing 13.16:

Listing 13.16. A Sample Interface
<?php
     interface printable {
          public function printme();
     }
?>

Interfaces, to be useful, must be implemented by one or more classes. In Listing 13.16 I have defined the printable interface, which dictates that any class implementing this interface must implement the printme() method. To create a class that implements an interface such as this, in the class definition the implements keyword is used, followed by a list of interfaces implemented (see Listing 13.17):

Listing 13.17. Implementing Interfaces
<?php
     class Integer implements printable {
          private $value;
          public function getValue() {
               return (int)$this->value;
          }
          public function printme() {
               echo (int)$this->value;
          }
     }
?>

In Listing 13.17, I have modified the original Integer class from Listing 13.15 to implement the printable interface defined in Listing 13.16. As a class that implements this interface, it has effectively ensured that the Integer class will provide those methods defined by the interface.

Now that I have defined a class that implements an interface, I can use that fact within my code to ensure that any functions or methods which require certain functionality from a class will have it available from the class, without checking for the specific class name using type hinting or the instanceof operator. Rather, you can use these techniques to specify the printable interface as shown in Listing 13.18:

Listing 13.18. Using Type Hinting with Interfaces
<?php
     interface printable {
          public function printme();
     }

     abstract class Number {
          private $value;
          abstract public function value();
          public function reset() {
               $this->value = NULL;
          }
     }

     class Integer extends Number implements printable {
          private $value;
          function __construct($value) {
               $this->value = $value;
          }
          public function getValue() {
               return (int)$this->value;
          }
          public function printme() {
               echo (int)$this->value;
          }
     }

     /* Create a function which requires the printable interface. */
     function printNumber(printable $myObject) {
          /* If this function is called, we can be
             certain that it has a printme() method */
          $myObject->printme();
     }
     $inst = new Integer(10);
     printNumber($inst);
?>

In Listing 13.18, interfaces have been used to ensure that the printNumber() function will always receive an object that has a printme() method. Another useful feature is that a single class can implement multiple different interfaces. An example is shown in Listing 13.19:

Listing 13.19. Implementing Multiple Interfaces
<?php
        interface printable {
                public function printme();
        }

        interface Inumber {
                public function reset();
        }

        class Integer implements printable, Inumber {
                private $value;

                function __construct($value) {
                        $this->value = $value;
                }

                public function printme() {
                        echo (int)$this->value;
                }

                public function reset() {
                        $this->value = NULL;
                }

                public function value() {
                        return (int)$this->value;
                }
        }

        function resetNumber(Inumber $obj) {
                $obj->reset();
        }

        function printNumber(printable $obj) {
                $obj->printme();
        }

        $inst = new Integer(10);
        printNumber($inst);
        resetNumber($inst);
?>

Final Classes and Methods

The concept of a final class or method is used to provide the developer a means of control over inheritance. Classes or methods declared as final cannot be extended and/or overloaded by child classes. To ensure that a particular class or method is never overloaded, simply add the final keyword to the method or class definition, as shown in Listing 13.20:

Listing 13.20. Declaring Final Classes and Methods
<?php
     final class NoExtending {
          public function myFunction() {
               /* Function logic */
          }
     }
     class restrictedExtending {
          final public function anotherFunc() {
               /* Function logic */
          }
     }
     class myChild extends restrictedExtending {
          public function thirdFunction() {
               /* Function logic */
          }
     }
?>

In Listing 13.20, three individual classes have been defined. The first of these classes, the NoExtending class, cannot ever be the parent of a child class because the entire class itself has been declared final. On the other hand, although the restrictedExtending class can be extended, the anotherFunc() method within it may never be overloaded by a child class. As you can see, the final keyword is useful to ensure that things are done in a particular way within your object structures while still allowing people to implement their own subclasses.

    Team LiB
    Previous Section Next Section