0
\$\begingroup\$

Im trying to teach myself enough to start using more OOP in php. This is what Ive come up with. Is there any reason why any of this is done wrong, or should be done another way?

    class workers {
            private $name;

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


            function setName($name){
                $this->name=$name;  
            }

            function doPrint($who){
                print $who->name . ' is ' . $who->isWhat() .'<br>';

            }

    }

    class boss extends workers{

            function isWhat(){
                return 'the boss';
            }

    }

    class bee extends workers{

            function isWhat(){
                return 'not the boss';
            }
    }


    $theboss =new boss('gordon');   
    $thebee= new bee('johnny');

        workers::doPrint($theboss);
        workers::doPrint($thebee);



    $theboss->setName('johnny');
    $thebee->setName('gordon');

        workers::doPrint($theboss);
        workers::doPrint($thebee);

prints:

gordon is the boss
johnny is not the boss
johnny is the boss
gordon is not the boss
\$\endgroup\$
1
  • 2
    \$\begingroup\$ note: make it isBoss, and return a boolean. \$\endgroup\$ – Karoly Horvath Jul 25 '12 at 19:46
4
\$\begingroup\$

you should use an abstract class and an interface. also define the doPrint method as static when you want to call it static.

abstract class worker {

    /*...*/

    public static function doPrint(worker_interface $who) {

        /*...*/
    }
}

interface worker_interface {

    public function isWhat();
    public function setName($name);
}

class boss extends worker implements worker_interface {


    public function isWhat() {

        return 'the boss';
    }
}

class bee extends worker implements worker_interface {


    public function isWhat() {

        return 'not the boss';
    }
}

define the type for all methods you are passing worker instances to like in doPrint

EDIT:

alternatively you could also just add an abstract function instead of using an interface

abstract class worker {

    /*...*/

    public static function doPrint(worker $who) {

        /*...*/
    }

    public abstract function isWhat();
}

class boss extends worker {


    public function isWhat() {

        return 'the boss';
    }
}

class bee extends worker {


    public function isWhat() {

        return 'not the boss';
    }
}
\$\endgroup\$
8
  • 1
    \$\begingroup\$ I agree. Although Johnny Craig's original post would work, this way is better because its easier to understand if you have tried to implement polymorphism in other languages. \$\endgroup\$ – james31rock Jul 25 '12 at 19:37
  • 1
    \$\begingroup\$ also it avoids wrong types to be passed to a function which then may result in a "method not found" or "not an object"-like error. \$\endgroup\$ – Andreas Linden Jul 25 '12 at 19:39
  • \$\begingroup\$ it would seem as that i am actually adding more code this way, that is considered good practice for readability. am i correct? also, by doing this, would you recommend to call new worker(), or new worker_interface() \$\endgroup\$ – johnny craig Jul 25 '12 at 19:43
  • 1
    \$\begingroup\$ you cannot instansiate an interface. \$\endgroup\$ – Karoly Horvath Jul 25 '12 at 19:44
  • 1
    \$\begingroup\$ you can't do both of them. abstract classes and interfaces cannot be instaciated. you do new boss; and new bee; \$\endgroup\$ – Andreas Linden Jul 25 '12 at 19:44
1
\$\begingroup\$

I would set the workers class as abstract (as pointed out by Andreas).

Also, I would use a shared member variable in the parent class which is set in each child's constructor. Also, I wouldn't use a static function to print the object as a string, that's more suited for __toString().

abstract class workers {
        private $name; 
        private $the_boss = false;

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

        function setName($name){
            $this->name=$name;  
        }

        function __toString(){
            return $this->name . ' is ' . ( $this->the_boss ? '' : 'not ' ).'the boss<br>';
        }
}

class boss extends workers {
    function __construct( $name) {
        parent::__construct( $name);
        $this->the_boss = true;
    }
}

class bee extends workers{
    function __construct( $name) {
        parent::__construct( $name);
    }
}

As you can see from the demo, this produces the same functionality as your original code.

An added benefit is the magic method __toString(), which allows you to do this:

echo $theboss;
echo $thebee;

Which causes PHP to invoke that method and print the string returned by __toString().

\$\endgroup\$
1
  • \$\begingroup\$ Thank you. i like the __toString bit. that will be very helpful in the future. \$\endgroup\$ – johnny craig Jul 25 '12 at 19:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.