PHP Objects, Patterns and Practice (3rd edition)

(Barry) #1

CHAPTER 3 ■ OBJECT BASICS


My Antonia: Willa Cather (5.99)


The ShopProductWriter class contains a single method, write(). The write() method accepts a
ShopProduct object and uses its properties and methods to construct and print a summary string. I used
the name of the argument variable, $shopProduct, as a signal that the method expects a ShopProduct
object, but I did not enforce this. That means I could be passed an unexpected object or primitive type
and be none the wiser until I begin trying to work with the $shopProduct argument. By that time, my
code may already have acted on the assumption that it has been passed a genuine ShopProduct object.


You might wonder why I didn't add the write() method directly to ShopProduct. The reason lies with areas of


responsibility. The ShopProduct class is responsible for managing product data; the ShopProductWriter is


responsible for writing it. You will begin to see why this division of labor can be useful as you read this chapter.


To address this problem, PHP 5 introduced class type hints. To add a type hint to a method
argument, you simply place a class name in front of the method argument you need to constrain. So I
can amend the write() method thus:


public function write( ShopProduct $shopProduct ) {
// ...
}


Now the write() method will only accept the $shopProduct argument if it contains an object of type
ShopProduct. Let’s try to call write() with a dodgy object:


class Wrong { }
$writer = new ShopProductWriter();
$writer->write( new Wrong() );


Because the write() method contains a class type hint, passing it a Wrong object causes a fatal error.

PHP Catchable fatal error: Argument 1 passed to ShopProductWriter::write() must be an
instance of ShopProduct, instance of Wrong given ...


This saves me from having to test the type of the argument before I work with it. It also makes the
method signature much clearer for the client coder. She can see the requirements of the write() method
at a glance. She does not have to worry about some obscure bug arising from a type error, because the
hint is rigidly enforced.
Even though this automated type checking is a great way of preventing bugs, it is important to
understand that hints are checked at runtime. This means that a class hint will only report an error at the
moment that an unwanted object is passed to the method. If a call to write() is buried in a conditional
clause that only runs on Christmas morning, you may find yourself working the holiday if you haven’t
checked your code carefully.
Type hinting cannot be used to enforce primitives like strings and integers in your arguments. For
these, you must fall back on type checking functions such as is_int() in the body of your methods. You
can, however, enforce array arguments:

Free download pdf