Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing child variables from parent class?

Tags:

php

class

How do I do this?

class test
{
    public static function run() {
        echo "Number is: ".$num;
    }
} 

class testchild extends test
{
    protected static $num = 5;
    public static function exec()  {
        $num = 5;
        parent::run();
    }
}

testchild::exec(); says Undefined variable "num".

http://ideone.com/WM7tHk

How do I access this variable?

like image 807
penu Avatar asked Jan 10 '23 21:01

penu


1 Answers

You shouldn't be able to do this, because you're requesting the parent to access something that it might be or not be there.

The simplest way would be to declare $num inside the parent. Otherwise you need to take measures to guarantee the system that the information will be there, by supplying (e.g.) a protected abstract static getter.

abstract class test
{
    public static function run() {
        echo "Number is: ".static::getNum();
    }
    protected abstract static function getNum();
}

class testchild extends test
{
    protected static $num;
    public static function exec()  {
        static::$num = 5;
        parent::run();
    }
    protected static function getNum() {
        return static::$num;
    }
}

class anotherchild extends test
{
    public static function exec()  {
        parent::run();
    }
    // We always return 42. Or maybe the Unix timestamp, who knows.
    protected static function getNum() {
        return 42;
    }
}


$c = new testchild();
$c->exec();

Passing several variables

Another, less solid approach would be to have a "communication object" and pass a reference to it. This can be done the same way as above, using a property array or (better) an object of known structure:

abstract class test
{
    public static function run() {
        echo "Number is: ".static::tell('num');
    }
    protected abstract static function tell($what);

    // A concrete function to initialize the known object would be nice here.
}

class testchild extends test
{
    protected static $info; // This is an array, out of laziness.
                            // It ought to be converted to an object.

    public static function exec()  {
        static::$info['num'] = 5;   // Typo here == possibly subtle bug.
        parent::run();
    }
    protected static function tell($what) {
        return static::$info[$what];  // array_key_exists would be nice here.
    }
}

Small improvement

To ensure that every object is on the same board when communicating, you can abstract the communication object (now it could also be an array) with a setter:

    public static function exec()  {
        static::say('num', 5);
        parent::run();
    }
    protected static function say($what, $value) {
        // array_key_exists would be nice here too.
        static::$info[$what] = $value;
    }

Then the initialization would set the object's keys to default values, and trying to set nonexisting keys could raise an exception. Of course you need to carefully plan what information needs to be set in the different child classes, and how; which isn't really a good practice, as changes would now tend to cascade from a child to the parent and thence to the siblings.

like image 179
LSerni Avatar answered Jan 21 '23 15:01

LSerni