Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I force a child class to use the parent's constructor?

I'm learning PHP and found some surprising behaviour when I was trying to figure out why a constructor wasn't getting called.

<?php
    class Shape {

        function __construct() { 
            echo 'Shape.';
        }
    }

    class Triangle extends Shape {

        function __construct() {        
            echo 'Triangle';
        }
    }

    $tri = new Triangle();
?>

I'm used to java, so I thought this would output "Shape. Triangle." Surprisingly, it just outputs "Triangle." I searched for the problem and apparently I can kinda sorta fix it by putting parent::__construct(); in the child class, but that doesn't seem ideal. Is there anything I can do to the Shape class to ensure that child classes always call the parent constructor? Do I really have to write parent::__construct(); in the class of every child whenever the parent has a constructor?

like image 279
Plain Jane Avatar asked Nov 08 '10 03:11

Plain Jane


1 Answers

As of PHP 5, you can use the final keyword to prevent a parent method from being overridden.

<?php
class BaseClass {
   public function test() {
       echo "BaseClass::test() called\n";
   }

   final public function moreTesting() {
       echo "BaseClass::moreTesting() called\n";
   }
}

class ChildClass extends BaseClass {
   public function moreTesting() {
       echo "ChildClass::moreTesting() called\n";
   }
}
// Results in Fatal error: Cannot override final method BaseClass::moreTesting()

You could use this in combination with a pre-defined init() method to ensure your parent constructor was called.

<?php
abstract class Shape {

    final function __construct() { 
        $this->init();
        echo 'Shape.';
    }

    abstract public function init();
}

class Triangle extends Shape {

    function init() {        
        echo 'Triangle';
    }
}

$tri = new Triangle();

This would output

TriangleShape.

It is advisable to only use a design like this if you document what the init() method does, and where it is called in the parent.

like image 82
MirroredFate Avatar answered Oct 06 '22 10:10

MirroredFate