Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP how to use parent-class object variables in extended classes? [duplicate]

Tags:

php

I'm sorry this appears to be a beginners question. How do I access a parent-class object variables in its extended classes?

class FOO {
  public $foo;
  function __construct() {
    $this->foo = 'string';
  }
}

class Parent {
  public $x;
  function __construct() {
    $this->x = new FOO();
    var_dump($x); // this works
  }
}

class Child extends Parent {
  public $y;
  function __construct() {
    var_dump($this->x); // appears to be NULL all the time
  }
}

how do I pass the value or reference of $x correctly?

like image 920
Larry Avatar asked Nov 30 '22 01:11

Larry


2 Answers

Your Child class has its own x property. Children inherit everything that isn't private, so all public and protected properties/methods will be available. You declare the property x, but it's not initialized until the Parent constructor is called. If a child class (in this case Child) has its own constructor, the parent constructor is overridden and will not be called automatically

In short: You have to call a parent's constructor explicitly from within the child class:

class Child extends Parent
{
    protected $y = 'Some string';//you can initialize properties here, too
    //ALWAYS use access modifiers
    public function __construct()
    {
        parent::__construct();//explicit call to parent constructor
        var_dump($this->x);
    }
}

Mind you: if the parent constructor expects an argument, then the child must do the same (signatures must match). The argument types should be compatible (if not: there's a breach of contract), and you'll probably want to pass the arguments to the parent constructor, for it to do its job, too.

Having constructors create new instances that the class needs internally is considered to be bad practice, BTW. Google : S.O.L.I.D., pay special attention to Dependency Injection and the Liskov Principle, and Type hinting.
If you read through the material, you'll understand why this is the better way to write your code:

class Dad
{
    /**
     * @var Foo
     */
    protected $x = null;

    public function __construct(Foo $foo)
    {
        $this->x = $foo;
    }
}
//child
class Son extends Dad
{
    /**
     * @var string
     */
    protected $y = 'Some string';

    public function __construct(Foo $foo)
    {
        parent::__construct($foo);
    }
    public function test()
    {
        $results = array();
        $results[] = '$this->x instanceof Foo ? '.($this->x instanceof Foo ? 'Of course!': 'No');
        $results[] '$this instanceof Son ? '.($this instanceof Son ? 'Yup' : 'No?');
        $results[] '$this instanceof Dad ? '.($this instanceof Dad ? 'Yes!' : 'No?');
        return $results;//methods don't echo, they return...
    }
}
$son = new Son(new Foo());
echo implode(PHP_EOL, $son->test());

The output of this code will be

$this->x instanceof Foo ? Of Course!
$this instanceof Son ? Yup
$this instanceof Dad ? Yes!

This seems to confuse many people who are (relatively) new to OOP, but a child class is of the same type as its parent. If you think about it, it makes sense. To the outside world (ie the code that works on/with an instance of a given class), only the public methods are visible. By definition, a child inherits everything that is public, so to the outside world, it doesn't really matter.
if some piece of code requires a Dad instance to do something, then a Son will work, too, because all that a Dad offers, a Son can do, too. The only thing a child class does is add to the functionality that a parent class already provides.

like image 52
Elias Van Ootegem Avatar answered Dec 04 '22 04:12

Elias Van Ootegem


You need to call Parent's constructor in Child's constructor, it's not called automatically :

class Child extends Parent {
    public $y;
    function __construct() {
       parent::__construct();
       var_dump($this->x); // appears to be NULL all the time
    }
}
like image 40
Erxyon Avatar answered Dec 04 '22 05:12

Erxyon