0

I have a parent class I'll be calling 'ParentClass' and a child class (that extends from it) which I'll be calling 'ChildClass'.

  • ParentClass has protected properties $prop1 and $prop2 which I want ChildClass to access. But I'm getting NULL from them.

  • ParentClass has a __construct() method which sets the properties received through dependency injection.

  • ParentClass instantiates ChildClass from one of its methods.

  • ChildClass overwrites the parent constructor, but doesn't contain any code inside of its own __construct() method.

I have already tested the properties at the parent class with var_dump($this->prop1). It returns the value I'm expecting.

However, if I var_dump($this->prop1) from the child class, I get NULL.

class ParentClass {

    protected $prop1;

    protected $prop2;

    public function __construct($prop1, $prop2) {

        $this->prop1 = $prop1;

        $this->prop2 = $prop2;

    }

    public function fakeMethod() {

        $child = new ChildClass;
        $child->anotherFakeMethod();

        // logic

    }

}
class ChildClass extends ParentClass {

    public function __construct() {

        // this overrides the parent constructor

    }

    public function anotherFakeMethod() {

        $prop1 = $this->prop1;
        $prop2 = $this->prop2;

        var_dump($this->prop1);
        // returns NULL

    }

}

Why can't the child class access the parent class' properties if it extends from it?

1
  • Your not injecting the data into the parent from the child constructor method. The reason it's null. If it was not "Accessible" you would get an error. Commented May 19, 2019 at 22:30

1 Answer 1

1

They are accessible, but they will be null because they are not passed to the parent constructor from the child:

(new ChildClass(1,2))->anotherFakeMethod();

Sandbox

Output

NULL

Your classes produce the expected result of null in this case. Well it produces what I would expect it to based on how it's coded.

To fix it, you must pass that data back to the parent class through the child's constructor, or remove the child's constructor. Like this:

class ChildClass extends ParentClass {

    public function __construct($prop1, $prop2) {
         parent::__construct($prop1, $prop2);
    }
....
}

After the above change:

(new ChildClass(1,2))->anotherFakeMethod();

Output

int(1)

Sandbox

Which is what I would expect from this line as it's basically the first argument used in the constructor:

var_dump($this->prop1);

You can also do it this way, if you know what they are in the child class:

public function __construct() {
     parent::__construct(1, 2); //say I know what these are for this child
}

You could of course set them manually in the new constructor but that would be WET (write everything twice) or unnecessary duplication, in this case.

Cheers!

6
  • Thank you. This works. However, I still don't understand why this is necessary. The parent class' constructor is called when it is instantiated, which populates the properties. So why do we have to do anything about it in the child class? Commented May 20, 2019 at 0:45
  • 1
    @Doug no it doesn't because you overrode it with a constructor that does nothing. Either don't override it, or do it like ArtisticPhoenix has suggested and use parent::__construct($prop1, $prop2);
    – Sammitch
    Commented May 20, 2019 at 0:45
  • What @Sammitch said. If you simply omitted it in the child then it would also work. Just because the parent has a method with the same name doesn't mean PHP should use the parents method instead of the child's (if it has the same), In fact its the opposite. PHP should and does use the method of the current class and fall back to the parent if it doesn't exist in the current class. If it worked the other way you could never override a method from a child class because it would always call the parents method, which is obviously not how it should work. Commented May 20, 2019 at 0:49
  • It can be confusing looking at just the code, but when you really think about how it works and spell it out, like I did above, you'll see it's the only way it can work. Commented May 20, 2019 at 0:52
  • Thanks again. I decided to simply not create the child class' constructor. When I instantiate the child from the parent, $prop1 and $prop2 are passed in its constructor. That way I write less code and accomplish what I want. Commented May 20, 2019 at 0:52

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