CHAPTER 4 ■ ADVANCED FEATURES
The problem here is that the abstract nature of the base class is only tested when an abstract
method is invoked. In PHP 5, abstract classes are tested when they are parsed, which is much safer.
Interfaces
While abstract classes let you provide some measure of implementation, interfaces are pure templates.
An interface can only define functionality; it can never implement it. An interface is declared with the
interface keyword. It can contain properties and method declarations, but not method bodies.
Here’s an interface:
interface Chargeable {
public function getPrice();
}
As you can see, an interface looks very much like a class. Any class that incorporates this interface
commits to implementing all the methods it defines or it must be declared abstract.
A class can implement an interface using the implements keyword in its declaration. Once you have
done this, the process of implementing an interface is the same as extending an abstract class that
contains only abstract methods. Now to make the ShopProduct class implement Chargeable.
class ShopProduct implements Chargeable {
// ...
public function getPrice() {
return ( $this->price - $this->discount );
}
// ...
ShopProduct already had a getPrice() method, so why might it be useful to implement the
Chargeable interface? Once again, the answer has to do with types. An implementing class takes on the
type of the class it extends and the interface that it implements.
This means that the CdProduct class belongs to
CdProduct
ShopProduct
Chargeable
This can be exploited by client code. To know an object’s type is to know its capabilities. So the
method
public function cdInfo( CdProduct $prod ) {
// ...
}
knows that the $prod object has a getPlayLength() method in addition to all the methods defined in the
ShopProduct class and Chargeable interface.
Passed the same object, the method
public function addProduct( ShopProduct $prod ) {
// ..
}
knows that $prod supports all the methods in ShopProduct, but without further testing, it will know
nothing of the getPlayLength() method.
Once again, passed the same CdProduct object, the method
public function addChargeableItem( Chargeable $item ) {