1

See the comment inside ChildEntity ::__construct():

class ChildEntity extends ParentEntity
{
    /** @var int */
    protected $classParameter;

    function __construct(int $classParameter)
    {
        /**
         * Question
         *
         * Below are the two ways of initializing the variable of ChildEntity
         *
         * Are they both initializing the same child(?) variable?
         * Are they initializing the parent(?) variable?
         * Can the child and parent have different values at the same time,
         * perhaps in different contexts?
         */
        $this->classParameter = $classParameter; // init local(?) variable?
        parent::__construct($classParameter); // init parent(?) variable?
    }
}

class ParentEntity
{
    /** @var int */
    protected $classParameter;

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

$childEntity = new ChildEntity(100);

Why does the below work (slightly different code - parameter removed in parent, and child uses only parent constructor to initialize). It looks like the parent class manipulates a variable found in the child class, without that variable being present in parent. It is as if the variable in ChildEntity and ParentEntity become one, and the child and parent instances also serve as a single instance, for all intents and purposes. Is that what actually happens behind the scenes?

class ChildEntity extends ParentEntity
{
    /** @var int */
    protected $classParameter;

    function __construct(int $classParameter)
    {
        parent::__construct($classParameter); 
        print $this->classParameter;
    }
}

class ParentEntity
{
    function __construct(int $classParameter)
    {
        $this->classParameter = $classParameter;
    }
}

$childEntity = new ChildEntity(5);

1 Answer 1

4

Are they both initializing the same child(?) variable?

When the object is created, all the non-private properties of all parent classes belong to this newly created object. He doesn't know which properties belong to class it was created with, and which ones belong to a parent one.

Can the child and parent have different values at the same time, perhaps in different contexts?

Only if you create two different objects, like that (I added a getter method):

$childEntity = new ChildEntity(5);
var_dump($childEntity->getClassParameter());

$parentEntity = new ParentEntity(6);
var_dump($parentEntity->getClassParameter());

Why does the below work?

When you write the following code:

class ParentEntity
{
    function __construct(int $classParameter)
    {
        $this->classParameter = $classParameter;
    }
}

that is, you initialize a property in a constructor without declaring it, php internally declares it itself. And when you create a ChildEntity, everything happens exactly the same as I already described. I should mention that php assigns this undeclared property a public visibility -- despite of, however crazy, it contradicts Liskov Substitution Principle. Check it out:

class ChildEntity extends ParentEntity
{
    /** @var int */
    protected $classParameter;

    function __construct(int $classParameter)
    {
        parent::__construct($classParameter);
        var_dump($this->classParameter);
    }

    public function getClassParameter()
    {
        return $this->classParameter;
    }
}

class ParentEntity
{
    function __construct(int $classParameter)
    {
        $this->classParameter = $classParameter;
    }
}

$parentEntity = new ParentEntity(6);
var_dump($parentEntity->classParameter);

$childEntity = new ChildEntity(5);
var_dump($childEntity->classParameter); // oops, an error!
3
  • hmm so there is a way to trick PHP into breaking LSP .....
    – Dennis
    Commented Jan 16, 2018 at 22:13
  • @Zapadlo That's a bad breach of LSP, wasn't aware of this one until now, thanks
    – e_i_pi
    Commented Jan 17, 2018 at 0:33
  • php is full of surprises :) Commented Jan 17, 2018 at 6:03

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