Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

class substitution in php

Is there any way to make it work? See example :

class car {
        function __construct($type){
                switch ($type) {
                        case 'big' : return new big_car();
                        case 'small' : return new small_car();
                }
        }
        function whatisit () {
                echo "this is car ;( \n";
        }
}

class big_car extends car {
        function __construct(){}
        function whatisit () {
                echo "this is big car ;) \n";
        }
}

class small_car extends car {
        function __construct(){}
        function whatisit () {
                echo "this is small car ;) \n";
        }
}

so the goal is to use it this way:

$mycar = new car('big');
$mycar->whatisit(); // i want it to say that it's big

I guess very much that its bad way and it cannot work this way but maybe there is a trick?

PS:: I know I can use special static method for that but...

like image 651
igor Avatar asked May 21 '13 18:05

igor


1 Answers

You need a car factory to create new cars; this is not JavaScript :)

class car_factory 
{
    function create_car($type = null) 
    {
        switch ($type) {
             case 'big':
                 return new big_car();

             case 'small':
                 return new small_car();

             case null:
                 return new car();
        }
        throw new InvalidArgumentException($type);
    }
}

$factory = new car_factory;
$small_car = $factory->create_car('small');
$std_car = $factory->create_car();

Of course, you should remove the __construct function from your original code.

As mentioned in the comments you could completely generalize this by using dynamic classes, assuming class extensions have the same constructor and class naming is consistent:

class car_factory
{
    function create_car($type = null)
    {
        if (is_null($type)) {
            return new car();
        }

        $class = "{$type}_car";
        if (class_exists($class)) {
            $obj = new $class();

            if ($obj instanceof car) {
                return $obj;
            }
        }

        throw new InvalidArgumentException($type);
    }
}

Personally I have no preferences either way; if extensibility is a key factor, go for it, otherwise stick with a simple switch.

like image 151
Ja͢ck Avatar answered Sep 24 '22 19:09

Ja͢ck