Book HomePHP CookbookSearch this book

7.10. Using Method Polymorphism

7.10.1. Problem

You want to execute different code depending on the number and type of arguments passed to a method.

7.10.2. Solution

PHP doesn't support method polymorphism as a built-in feature. However, you can emulate it using various type-checking functions. The following combine( ) function uses is_numeric(), is_string(), is_array(), and is_bool():

// combine() adds numbers, concatenates strings, merges arrays,
// and ANDs bitwise and boolean arguments
function combine($a, $b) {
    if (is_numeric($a) && is_numeric($b)) {
        return $a + $b;
    }

    if (is_string($a)  && is_string($b))  {
        return "$a$b";
    }

    if (is_array($a)   && is_array($b))   {
        return array_merge($a, $b);
    }

    if (is_bool($a)    && is_bool($b))    {
        return $a & $b;
    }

    return false;
}

7.10.3. Discussion

Because PHP doesn't allow you to declare a variable's type in a method prototype, it can't conditionally execute a different method based on the method's signature, as can Java and C++. You can, instead, make one function and use a switch statement to manually recreate this feature.

For example, PHP lets you edit images using GD. It can be handy in an image class to be able to pass in either the location of the image (remote or local) or the handle PHP has assigned to an existing image stream. Example 7-2 shows a pc_Image class that does just that.

Example 7-2. pc_Image class

class pc_Image {

    var $handle;

    function ImageCreate($image) {
        if (is_string($image)) {
            // simple file type guessing

            // grab file suffix
            $info = pathinfo($image);
            $extension = strtolower($info['extension']);
            switch ($extension) {
            case 'jpg':
            case 'jpeg':
                $this->handle = ImageCreateFromJPEG($image);
                break;
            case 'png':
                $this->handle = ImageCreateFromPNG($image);
                break;
            default:
                die('Images must be JPEGs or PNGs.');
            }
        } elseif (is_resource($image)) {
            $this->handle = $image;
        } else {
            die('Variables must be strings or resources.');
        }
    }
}

In this case, any string passed in is treated as the location of a file, so we use pathinfo() to grab the file extension. Once we know the extension, we try to guess which ImageCreateFrom( ) function accurately opens the image and create a handle.

If it's not a string, we're dealing directly with a GD stream, which is of type resource. Since there's no conversion necessary, we assign the stream directly to $handle. Of course, if you're using this class in a production environment, you'd be more robust in your error handling.

Method polymorphism also encompasses methods with differing numbers of arguments. The code to find the number of arguments inside a method is identical to how you process variable argument functions using func_num_args( ). This is discussed in Recipe 6.6.

7.10.4. See Also

Recipe 6.6 for variable argument functions; documentation on is_string( ) at http://www.php.net/is-string, is_resource( ) at http://www.php.net/is-resource, and pathinfo( ) at http://www.php.net/pathinfo.



Library Navigation Links

Copyright © 2003 O'Reilly & Associates. All rights reserved.